Skip to content Skip to sidebar Skip to footer

Crash On Call From Boost::python::exec( Anything )

I'm trying to implement some Python stuff into my program and I've decided to use Boost::Python, so I compiled it according to the instructions, with bjam, using mingw/gcc, getting

Solution 1:

When embedding Python, almost all calls to Python or Boost.Python should occur after the interpreter has been initialized with Py_Initialize(). Trying to invoke the interpreter before initialization, such as with boost::python::exec(), will result in undefined behavior.

While that identifies the source of the crash, there are some subtle details to obtain the accomplish the final goal of embedding Python and a module, then have exec import the embedded module.

  • When importing a module, Python will first check if the module is a built-in module. If the module is not a built-in module, then Python will try to load a library based on the module name, and expects the library to provide a function that will initialize the module. As the test_module is being embedded, its initialization needs to be explicitly added so that import can find it when searching for built-in modules.
  • The import statement uses the __import__ function. This function needs to be available within exec's globals.

Here is a complete example demonstrating how to accomplish this:

#include<boost/python.hpp>floatfunc(int a){
  return a*a-0.5;
}

BOOST_PYTHON_MODULE(test_module)
{
  usingnamespace boost::python;
  def("func", func);
}

// Use macros to account for changes in Python 2 and 3:// - Python's C API for embedding requires different naming conventions for//   module initialization functions.// - The builtins module was renamed.#if PY_VERSION_HEX >= 0x03000000#  define MODULE_INIT_FN(name) BOOST_PP_CAT(PyInit_, name)#  define PYTHON_BUILTINS "builtins"#else#  define MODULE_INIT_FN(name) BOOST_PP_CAT(init, name)#  define PYTHON_BUILTINS "__builtin__"#endifintmain(){
  // Add the test_module module to the list of built-in modules.  This// allows it to be imported with 'import test_module'.PyImport_AppendInittab("test_module", &MODULE_INIT_FN(test_module));

  Py_Initialize();

  namespace python = boost::python;
  try
  {
    // Create an empty dictionary that will function as a namespace.
    python::dict ns;

    // The 'import' statement depends on the __import__ function.  Thus,// to enable 'import' to function the context of 'exec', the builtins// module needs to be within the namespace being used.
    ns["__builtins__"] = python::import(PYTHON_BUILTINS);

    // Execute code.  Modifications to variables will be reflected in// the ns.
    python::exec("b = 5", ns);

    std::cout << "b is " << python::extract<int>(ns["b"]) << std::endl;

    // Execute code using the built-in test_module.
    python::exec(
      "import test_module\n""var = test_module.func(b)\n",
      ns);

    std::cout << "var is " << python::extract<float>(ns["var"]) << std::endl;
  }
  catch (python::error_already_set&)
  {
    PyErr_Print();
  }
}

When executed, its output is:

b is 5
var is 24.5

Post a Comment for "Crash On Call From Boost::python::exec( Anything )"