Можно ли загрузить функцию python из строки, а затем вызвать эту функцию с аргументами и получить возвращаемое значение?
Я использую API Python C для запуска кода Python из моего приложения C ++.,Я могу загрузить модуль из файла, используя 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