First I'll restate the question: When embedding Python into a C/C++ application using python docs and other resources. I discovered that you can import a module using
PyObject *pName = PyUnicode_FromString((char*)"scipy");
PyObject *pModule = PyImport_Import(pName);
but if I try to import "scipy.optimize"
PyObject *pName = PyUnicode_FromString((char*)"scipy.optimize");
PyObject *pModule = PyImport_Import(pName);
then the program fails to initialize pModule
. Again if I try
PyObject *pName = PyUnicode_FromString((char*)"scipy");
PyObject *pModule = PyImport_Import(pName);
pFunc = PyObject_GetAttrString(pModule, (char*)"optimize.nnls");
where I put optimize
in the function name the it fails to initialize pFunc
. How do I import or call a function in a submodule, i.e. how do I call the function scipy.optimize.nnls?
Next, I'll lay out my code in case it helps:
/* Relelvant imports
#include <Python.h>
#include <numpy/arrayobject.h>
*/
void nnls::update(const vec& x, const vec& y)
{
mat B;
vecToGslVec(x, gslx);
generateX(X, gslx);
A = gslMatToMat(X);
B = A.transpose();
long double *c_out;
Py_Initialize();
PyObject *pName = PyUnicode_FromString((char*)"scipy"); //Issue Here
check(pName, "pName not initializes.");
PyObject *pModule = PyImport_Import(pName);
check(pModule, "pModule not initializes.");
PyObject *pFunc, *pArgs, *pResult;
PyArrayObject *pNpArray;
npy_intp Adims[2]; Adims[0] = A.rows(); Adims[1] = A.cols();
npy_intp bdim[1]; bdim[0] = y.size();
if (pModule != NULL) {
pFunc = PyObject_GetAttrString(pModule, (char*)"optimize.nnls"); //Issue Here
check(pFunc, "pFunc not initializes.");
/*program never advances past this point unless I remove this check,
in which case I get a segfault, because pFunc is not initialized.*/
if (pFunc && PyCallable_Check(pFunc)) {
pArgs = PyTuple_Pack(2,
PyArray_SimpleNewFromData(2, Adims, NPY_FLOAT, B.data()),
PyArray_SimpleNewFromData(1, bdim , NPY_FLOAT, \
const_cast<double*> (y.data()))
);
check(pArgs, "pArgs not initializes.");
pResult = PyObject_CallObject(pFunc, pArgs);
check(pResult, "pResult not initializes.");
pNpArray = reinterpret_cast<PyArrayObject*>(pResult);
log_info("not PyArray cast");
}
Py_DECREF(pFunc);
}
Py_DECREF(pModule);
Py_DECREF(pArgs);
c_out = reinterpret_cast<long double*>(PyArray_DATA(pNpArray));
for(size_t i=0; i<order; i++){
gsl_vector_set(gslc, i, c_out[i]);
}
if (pResult != NULL) Py_DECREF(pResult); Py_DECREF(pNpArray);
Py_Finalize();
}
Again, My issue is in the lines
PyObject *pModule = PyImport_Import(pName);
and
pFunc = PyObject_GetAttrString(pModule, (char*)"optimize.nnls");
If I set
pName = PyUnicode_FromString((char*)"scipy.optimize");
or
pFunc = PyObject_GetAttrString(pModule, (char*)"optimize.nnls");
the code fails to initialized these variables at these points.
So to reiterate my question one last time how do I import the module scipy.optimize
or call the function optimize.nnls
in this context? Thanks. I hope it isn't too confusing, if it is let me know and I'll clarify.
First of all, I've never use PyImport_Import()
. I've always used PyImport_ImportModule()
, which takes a const char *
arg instead of a PyObject *
. That should save some steps in your code.
PyObject *pModule = PyImport_ImportModule("scipy.optimize");
PyObject *pFunc = PyObject_GetAttrString(pModule, "nnls");
This is how I have done things in code I have written. PyImport_ImportModule()
handles package hierarchies. PyObject_getAttrString()
does not know what to do with the dot.
I have never used PyImport_Import()
, so I don't know how its behavior might change things.