If I understand the question correctly, then it should be as simple as specifying the context in which exec
will execute. A function or method can access the namespace in which it is defined via globals()
. Thus, calling globals()
from within runPyProg()
will return the Python equivalent of main_namespace
. Additionally, exec
takes two optional arguments:
- The first argument specifies the dictionary that will be used for
globals()
. If the second argument is omitted, then it is also used forlocals()
. - The second argument specifies the dictionary that will be used for
locals()
. Variable changes occurring withinexec
are applied tolocals()
.
Therefore, change:
exec exp
to
exec exp in globals()
and it should provide the desired behavior, where exp
can interact with global variables in main_namespace
.
Here is a basic example:
#include <boost/python.hpp>
int main()
{
Py_Initialize();
namespace python = boost::python;
python::object main = python::import("__main__");
python::object main_namespace = main.attr("__dict__");
//Put the function name runPyProg in the main_namespace
python::exec(
"def runPyProg(exp):\n"
" print exp\n"
" exec exp in globals()\n"
" return\n"
"\n", main_namespace);
// Now call the python function runPyProg with an argument
python::object runPyProg = main.attr("runPyProg");
// Set x in python and access from C++.
runPyProg("x = 42");
std::cout << python::extract<int>(main.attr("x")) << std::endl;
// Set y from C++ and access within python.
main.attr("y") = 100;
runPyProg("print y");
// Access and modify x in python, then access from C++.
runPyProg("x += y");
std::cout << python::extract<int>(main.attr("x")) << std::endl;
}
Commented output:
x = 42 // set from python
42 // print from C++
// y set to 100 from C++
print y // print y from python
100 //
x += y // access and modify from python
142 // print x from C++