Crash on call from boost::python::exec( anything )
Question: 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 dlls and .a files  
I'm using Code::Blocks for this, so I've put the dlls in the working directory
of my project, where the rest of dlls I use are, and decided to run
`boost::python::exec("b = 5");`  
Instantly I get a crash. Ideas?  
  

    
    
    #include <boost/python.hpp>
    
    float func(int a)
    {
      return a*a-0.5;
    }
    
    BOOST_PYTHON_MODULE(test_module)
    {
      using namespace boost::python;
      def("func", func);
    }
    
    int main()
    {
      //Try one
      boost::python::exec("b = 5");
      //Crash
    
      //Try two
      Py_Initialize();
      boost::python::exec("b = 5");
      //Works fine
    
      //Try three
      Py_Initialize();
      boost::python::exec("import test_module");
      //Throws boost::python::error_already_set and crashes
    
      /*
        Something along the lines of
        boost::python::exec("import test_module\n"
                            "var = test_module.func( 3 )\n");
      */    
    }
    

Under the build options section of my project, I've added
`libboost_python3-mgw48-d-1_54.dll` and `libpython33` to be linked so it'd
compile.  
Ideas?


Answer: When embedding Python, almost all calls to Python or Boost.Python should occur
after the interpreter has been initialized with
[`Py_Initialize()`](http://docs.python.org/3.3/c-api/init.html#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>
    
    float func(int a)
    {
      return a*a-0.5;
    }
    
    BOOST_PYTHON_MODULE(test_module)
    {
      using namespace 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__"
    #endif
    
    int main()
    {
      // 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
    

