在另一个应用程序中嵌入 python 时,如何导入或调用子模块中的函数(即 scipy.optimize.nnls)?
When embedding python in another application how do I import or call a function in a submodule (i.e. scipy.optimize.nnls)?
首先,我将重述问题:使用 python docs 和其他资源将 Python 嵌入到 C/C++ 应用程序时。我发现您可以使用
导入模块
PyObject *pName = PyUnicode_FromString((char*)"scipy");
PyObject *pModule = PyImport_Import(pName);
但是如果我尝试导入 "scipy.optimize"
PyObject *pName = PyUnicode_FromString((char*)"scipy.optimize");
PyObject *pModule = PyImport_Import(pName);
然后程序无法初始化pModule
。如果我再次尝试
PyObject *pName = PyUnicode_FromString((char*)"scipy");
PyObject *pModule = PyImport_Import(pName);
pFunc = PyObject_GetAttrString(pModule, (char*)"optimize.nnls");
我在函数名称中放置 optimize
的地方它无法初始化 pFunc
。如何在子模块中导入或调用函数,即如何调用函数 scipy.optimize.nnls?
接下来,我将列出我的代码以备不时之需:
/* 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();
}
同样,我的问题在行
PyObject *pModule = PyImport_Import(pName);
和
pFunc = PyObject_GetAttrString(pModule, (char*)"optimize.nnls");
如果我设置
pName = PyUnicode_FromString((char*)"scipy.optimize");
或
pFunc = PyObject_GetAttrString(pModule, (char*)"optimize.nnls");
代码无法在这些点初始化这些变量。
所以最后一次重申我的问题,我如何在这种情况下导入模块 scipy.optimize
或调用函数 optimize.nnls
?谢谢。我希望它不会太混乱,如果它让我知道,我会澄清。
就像很少使用的内置 __import__
函数一样,当您 PyImport_Import
名称 scipy.optimize
时,导入系统确实会加载 scipy.optimize
模块,但是它returns scipy
而不是 scipy.optimize
。您需要沿着属性链一直向下到 scipy.optimize.nnls
:
PyObject *scipy = PyImport_Import(pName);
PyObject *optimize = PyObject_GetAttrString(scipy, "optimize");
PyObject *nnls = PyObject_GetAttrString(optimize, "nnls");
一如既往,不要忘记 Py_DECREF
在您处理完所有参考资料后。这包括 pName
.
首先,我从来没有用过PyImport_Import()
。我一直使用 PyImport_ImportModule()
,它接受 const char *
arg 而不是 PyObject *
。这应该可以在您的代码中节省一些步骤。
PyObject *pModule = PyImport_ImportModule("scipy.optimize");
PyObject *pFunc = PyObject_GetAttrString(pModule, "nnls");
这就是我在编写的代码中做事的方式。 PyImport_ImportModule()
处理包层次结构。 PyObject_getAttrString()
不知道如何处理点。
我从未使用过 PyImport_Import()
,所以我不知道它的行为会如何改变。
首先,我将重述问题:使用 python docs 和其他资源将 Python 嵌入到 C/C++ 应用程序时。我发现您可以使用
导入模块PyObject *pName = PyUnicode_FromString((char*)"scipy");
PyObject *pModule = PyImport_Import(pName);
但是如果我尝试导入 "scipy.optimize"
PyObject *pName = PyUnicode_FromString((char*)"scipy.optimize");
PyObject *pModule = PyImport_Import(pName);
然后程序无法初始化pModule
。如果我再次尝试
PyObject *pName = PyUnicode_FromString((char*)"scipy");
PyObject *pModule = PyImport_Import(pName);
pFunc = PyObject_GetAttrString(pModule, (char*)"optimize.nnls");
我在函数名称中放置 optimize
的地方它无法初始化 pFunc
。如何在子模块中导入或调用函数,即如何调用函数 scipy.optimize.nnls?
接下来,我将列出我的代码以备不时之需:
/* 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();
}
同样,我的问题在行
PyObject *pModule = PyImport_Import(pName);
和
pFunc = PyObject_GetAttrString(pModule, (char*)"optimize.nnls");
如果我设置
pName = PyUnicode_FromString((char*)"scipy.optimize");
或
pFunc = PyObject_GetAttrString(pModule, (char*)"optimize.nnls");
代码无法在这些点初始化这些变量。
所以最后一次重申我的问题,我如何在这种情况下导入模块 scipy.optimize
或调用函数 optimize.nnls
?谢谢。我希望它不会太混乱,如果它让我知道,我会澄清。
就像很少使用的内置 __import__
函数一样,当您 PyImport_Import
名称 scipy.optimize
时,导入系统确实会加载 scipy.optimize
模块,但是它returns scipy
而不是 scipy.optimize
。您需要沿着属性链一直向下到 scipy.optimize.nnls
:
PyObject *scipy = PyImport_Import(pName);
PyObject *optimize = PyObject_GetAttrString(scipy, "optimize");
PyObject *nnls = PyObject_GetAttrString(optimize, "nnls");
一如既往,不要忘记 Py_DECREF
在您处理完所有参考资料后。这包括 pName
.
首先,我从来没有用过PyImport_Import()
。我一直使用 PyImport_ImportModule()
,它接受 const char *
arg 而不是 PyObject *
。这应该可以在您的代码中节省一些步骤。
PyObject *pModule = PyImport_ImportModule("scipy.optimize");
PyObject *pFunc = PyObject_GetAttrString(pModule, "nnls");
这就是我在编写的代码中做事的方式。 PyImport_ImportModule()
处理包层次结构。 PyObject_getAttrString()
不知道如何处理点。
我从未使用过 PyImport_Import()
,所以我不知道它的行为会如何改变。