Python embedded in CPP: how to get data back to CPP
boost-python, c++, python
Solution
First of all, change your function to `return` the value. `print`ing it will complicate things since you want to get the value back. Suppose your `MyModule.py` looks like this:
import thirdparty
def MyFunc(some_arg):
result = thirdparty.go()
return result
Now, to do what you want, you have to go beyond basic embedding, as the documentation says. Here is the full code to run your function:
#include <Python.h>
int
main(int argc, char *argv[])
{
PyObject *pName, *pModule, *pFunc;
PyObject *pArgs, *pArg, *pResult;
int i;
Py_Initialize();
pName = PyString_FromString("MyModule.py");
/* Error checking of pName left out as exercise */
pModule = PyImport_Import(pName);
Py_DECREF(pName);
if (pModule != NULL) {
pFunc = PyObject_GetAttrString(pModule, "MyFunc");
/* pFunc is a new reference */
if (pFunc) {
pArgs = PyTuple_New(0);
pArg = PyString_FromString("some parameter")
/* pArg reference stolen here: */
PyTuple_SetItem(pArgs, 0, pArg);
pResult = PyObject_CallObject(pFunc, pArgs);
Py_DECREF(pArgs);
if (pResult != NULL) {
printf("Result of call: %s\n", PyString_AsString(pResult));
Py_DECREF(pResult);
}
else {
Py_DECREF(pFunc);
Py_DECREF(pModule);
PyErr_Print();
fprintf(stderr,"Call failed\n");
return 1;
}
}
else {
if (PyErr_Occurred())
PyErr_Print();
fprintf(stderr, "Cannot find function");
}
Py_XDECREF(pFunc);
Py_DECREF(pModule);
}
else {
PyErr_Print();
fprintf(stderr, "Failed to load module");
return 1;
}
Py_Finalize();
return 0;
}
Problem
While working on a C++ project, I was looking for a third party library for something that is not my core business. I found a really good library, doing exactly what's needed, but it is written in Python. I decided to experiment with embedding Python code in C++, using the Boost.Python library. The C++ code looks something like this: ``` #include <string> #include <iostream> #include <boost/python.hpp> using namespace boost::python; int main(int, char **) { Py_Initialize(); try { object module((handle<>(borrowed(PyImport_AddModule("__main__"))))); object name_space = module.attr("__dict__"); object ignored = exec("from myModule import MyFunc\n" "MyFunc(\"some_arg\")\n", name_space); std::string res = extract<std::string>(name_space["result"]); } catch (error_already_set) { PyErr_Print(); } Py_Finalize(); return 0; } ``` A (very) simplified version of the Python code looks like this: ``` import thirdparty def MyFunc(some_arg): result = thirdparty.go() print result ``` Now the problem is this: 'MyFunc' executes fine, i can see the print of 'result'. What i cannot do is read 'result' back from the C++ code. The extract command never finds 'result' in any namespace. I tried defining 'result' as a global, i even tried returning a tuple, but i cannot get it to work.