Python Embedded in C++
Question: So I have a GUI program that has a great deal of "stuff" going on. I am adding
a python scripting interface so someone can interact problematically with this
environment. I am using boost python. So first thing I have is a new module I
want to create. For simplicity right now my module just is hello world...

    
    
    #include <boost/python.hpp>                                                     
    
    char const* greet() {                                                           
       return "hello, world" ;                                                      
    }                                                                               
    
    BOOST_PYTHON_MODULE(cerrnimapi) {                                               
      boost::python::def( "greet", greet ) ;                                        
    }  
    

In my system I have a class that looks like this...

    
    
    Controller::Controller( ) {         
      Py_Initialize( ) ;                                                            
    
      main_module = boost::python::import( "__main__" ) ;                           
      main_namespace = main_module.attr( "__dict__" ) ;                             
    }                                                                                                                                                     
    
    void Controller::execute_script( std::string filename ) {                       
      try {                                                                         
        boost::python::api::object ignored =                                        
          boost::python::exec_file( filename.c_str(), main_namespace ) ;            
      } catch( boost::python::error_already_set const & ) {                         
        if (PyErr_ExceptionMatches(PyExc_ZeroDivisionError)) {                      
        } else {                                                                    
            PyErr_Print();                                                          
        }                                                                           
      }                                                                             
    }
    

Now when I go to execute the script in the GUI I get an error...

    
    
    Traceback (most recent call last):
      File "/home/mokon/repository/trunk/python.py", line 1, in <module>
        import cerrnimapi
    ImportError: No module named cerrnimapi
    

So of course I am building something wrong. My build system uses autotools so
here are a few pieces of that build system that relate to this...

In configure.ac:

    
    
    AM_PATH_PYTHON                                                                  
    AC_ARG_VAR([PYTHON_INCLUDE], [Include flags for python, bypassing python-config])
    AC_ARG_VAR([PYTHON_CONFIG], [Path to python-config])                            
    AS_IF([test -z "$PYTHON_INCLUDE"], [                                            
      AS_IF([test -z "$PYTHON_CONFIG"], [                                           
        AC_PATH_PROGS([PYTHON_CONFIG],                                              
                      [python$PYTHON_VERSION-config python-config],                 
                      [no],                                                         
                      [`dirname $PYTHON`])                                          
        AS_IF([test "$PYTHON_CONFIG" = no], [AC_MSG_ERROR([cannot find python-config for $PYTHON.])])
      ])                                                                            
      AC_MSG_CHECKING([python include flags])                                       
      PYTHON_INCLUDE=`$PYTHON_CONFIG --includes`                                    
      AC_MSG_RESULT([$PYTHON_INCLUDE])                                              
    ])                                                                              
    
    AC_ARG_VAR([PYTHON_LD], [Linker flags for python, bypassing python-config])     
    AS_IF([test -z "$PYTHON_LD"], [                                                 
      AS_IF([test -z "$PYTHON_CONFIG"], [                                           
        AC_PATH_PROGS([PYTHON_CONFIG],                                              
                      [python$PYTHON_VERSION-config python-config],                 
                      [no],                                                         
                      [`dirname $PYTHON`])                                          
        AS_IF([test "$PYTHON_CONFIG" = no], [AC_MSG_ERROR([cannot find python-config for $PYTHON.])])
      ])                                                                            
      AC_MSG_CHECKING([python linker flags])                                        
      PYTHON_LD=`$PYTHON_CONFIG --ldflags`                                          
      AC_MSG_RESULT([$PYTHON_LD])                                                   
    ]) 
    

In my obj/ dir Makefile.am...

    
    
    pyexec_LTLIBRARIES = cerrnimapi.la                                              
    cerrnimapi_la_SOURCES = ${SRC_DIR}/lib/PythonAPI.cpp                            
    cerrnimapi_la_LDFLAGS = -avoid-version -module $(PYTHON_LD)                     
    cerrnimapi_la_CXXFLAGS = $(PYTHON_INCLUDE)  
    

My makefile builds the shared lib and its in the obj folder along with my main
program. This doesn't help. I have also done a make install to install the
cerrnimapi lib in the python folders. This doesn't help.

I have also tried adding the PythonAPI.cpp to my main programs SOURCES but to
no avail.

Any ideas? let me know what additional information would be helpful.


Answer: Some things to check:

  * Run `nm` over your .so file (which might be in `.libs`) to make sure your module init func is exported.
  * Make your program print out the value of `sys.path` (use PyRun_SimpleString) to see where it's expecting your module to turn up. If you're defining modules for your interpreter only, you probably don't want to install them in `$pyexecdir`.
  * Read the [Extending Embedded Python](http://docs.python.org/2/extending/embedding.html#extending-embedded-python) article. You don't really need to build dynamic libraries at all, unless you're trying for a plugin architecture.

A point on style: You should try and find `$PYTHON_CONFIG` outside of your
tests for `$PYTHON_INCLUDE` and `$PYTHON_LD` so you're not doing the
`AC_PATH_PROGS` twice:

    
    
    AM_PATH_PYTHON                                                                  
    AC_ARG_VAR([PYTHON_CONFIG], [Path to python-config])                            
    AS_IF([test -z "$PYTHON_CONFIG"], [                                           
      AC_PATH_PROGS([PYTHON_CONFIG],                                              
                    [python$PYTHON_VERSION-config python-config],                 
                    [no],                                                         
                    [`dirname $PYTHON`])                                          
    ])                                                                            
    
    AC_ARG_VAR([PYTHON_INCLUDE], [Include flags for python, bypassing python-config])
    AS_IF([test -z "$PYTHON_INCLUDE"], [                                            
      AC_MSG_CHECKING([python include flags])                                       
      AS_IF([test "$PYTHON_CONFIG" = no], [AC_MSG_ERROR([cannot find python-config for $PYTHON.])])
      PYTHON_INCLUDE=`$PYTHON_CONFIG --includes`                                    
      AC_MSG_RESULT([$PYTHON_INCLUDE])                                              
    ])                                                                              
    
    AC_ARG_VAR([PYTHON_LD], [Linker flags for python, bypassing python-config])     
    AS_IF([test -z "$PYTHON_LD"], [                                                 
      AC_MSG_CHECKING([python linker flags])                                        
      AS_IF([test "$PYTHON_CONFIG" = no], [AC_MSG_ERROR([cannot find python-config for $PYTHON.])])
      PYTHON_LD=`$PYTHON_CONFIG --ldflags`                                          
      AC_MSG_RESULT([$PYTHON_LD])                                                   
    ])
    

