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.
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 yourMyModule.py
looks like this: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:
You should be able to return the result from MyFunc, which would then end up in the variable you are currently calling "ignored". This eliminates the need to access it in any other way.
I think what you need is either
PyObject_CallObject(<py function>, <args>)
, which returns the return value of the function you call as a PyObject, orPyRun_String(<expression>, Py_eval_input, <globals>, <locals>)
which evaluates a single expression and returns its result.Based on ΤΖΩΤΖΙΟΥ, Josh and Nosklo's answers i finally got it work using boost.python:
Python:
C++:
Some important points: