【发布时间】:2011-04-16 22:26:41
【问题描述】:
是否可以从字符串加载python函数,然后用参数调用该函数并获取返回值?
我正在使用 python C API 从我的 C++ 应用程序中运行 python 代码。我可以使用PyImport_Import 从文件中加载一个模块,使用PyObject_GetAttrString 从该文件中获取一个函数对象,然后使用PyObject_CallObject 调用该函数。我想做的是从字符串而不是文件加载模块/函数。是否有一些等效于PyImport_Import 的方法可以让我将字符串而不是文件传递给它?我需要将参数传递给我正在调用的函数,并且我需要访问返回值,所以我不能只使用PyRun_SimpleString。
编辑:
我在打开PyRun_String 后找到了这个解决方案。我正在创建一个新模块,获取它的字典对象,将其传递给PyRun_String 以在我的新模块中定义一个函数,然后为该新创建的函数获取一个函数对象并通过PyObject_CallObject 调用它,传递我的参数。这是我发现解决我的问题的方法:
main.cpp
int main()
{
PyObject *pName, *pModule, *pArgs, *pValue, *pFunc;
PyObject *pGlobal = PyDict_New();
PyObject *pLocal;
//Create a new module object
PyObject *pNewMod = PyModule_New("mymod");
Py_Initialize();
PyModule_AddStringConstant(pNewMod, "__file__", "");
//Get the dictionary object from my module so I can pass this to PyRun_String
pLocal = PyModule_GetDict(pNewMod);
//Define my function in the newly created module
pValue = PyRun_String("def blah(x):\n\tprint 5 * x\n\treturn 77\n", Py_file_input, pGlobal, pLocal);
Py_DECREF(pValue);
//Get a pointer to the function I just defined
pFunc = PyObject_GetAttrString(pNewMod, "blah");
//Build a tuple to hold my arguments (just the number 4 in this case)
pArgs = PyTuple_New(1);
pValue = PyInt_FromLong(4);
PyTuple_SetItem(pArgs, 0, pValue);
//Call my function, passing it the number four
pValue = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pArgs);
printf("Returned val: %ld\n", PyInt_AsLong(pValue));
Py_DECREF(pValue);
Py_XDECREF(pFunc);
Py_DECREF(pNewMod);
Py_Finalize();
return 0;
}
这是我原来的帖子的其余部分,留给后代:
这是我最初的做法:
main.cpp:
#include <Python.h>
int main()
{
PyObject *pName, *pModule, *pArgs, *pValue, *pFunc;
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('')");
pName = PyString_FromString("atest");
pModule = PyImport_Import(pName);
Py_DECREF(pName);
if(pModule == NULL)
{
printf("PMod is null\n");
PyErr_Print();
return 1;
}
pFunc = PyObject_GetAttrString(pModule, "doStuff");
pArgs = PyTuple_New(1);
pValue = PyInt_FromLong(4);
PyTuple_SetItem(pArgs, 0, pValue);
pValue = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pArgs);
printf("Returned val: %ld\n", PyInt_AsLong(pValue));
Py_DECREF(pValue);
Py_XDECREF(pFunc);
Py_DECREF(pModule);
Py_Finalize();
return 0;
}
还有atest.py:
def doStuff( x):
print "X is %d\n" % x
return 2 * x
【问题讨论】:
-
没有必要为后代留下您的帖子。 Stack Overflow 已经涵盖了这一点。对问题和答案的所有编辑都会自动存档,一旦我们的分数达到一定水平,我们就可以看到。这有助于我们回滚错误的编辑,并跟踪更改以更好地理解问题。因此,您可以删除您的更改,而不是将其留在那里,如果需要,我们可以查看编辑日志。因此,甚至不需要输入“编辑:”。
-
对于其他偶然发现此问题的人:在第一个代码 sn-p 中,调用 Py_Initialize 为时已晚。只是你知道
-
检查是否使用pValue两次第一次引用一定会造成内存泄漏