Search code examples
pythonc++boostboost-python

How to compile, create shared library, and import c++ boost module in Python


I see there are tons of information on the Web about how to compile c++ modules for Python. But the problem is, practically any programmer has his own way of compiling and his own list of flags and another tricks. So, taking into account such a variety of tricks, I can't decide which method I should use and besides I have some other questions. This is what I tried:

// part of main.cpp file
....
BOOST_PYTHON_MODULE( orm ){
    class_<ORM>( "ORM",
    // other code goes here
}

My first question is how I will include this module in Python in the long run? Should I do it like:

  import orm

Or will it depend on the name of object file created during compilation process?

My second question is how to compile the module and prepare it for Python? Now I do it like so:

$ g++ -I /usr/include/python2.7 -fpic -c -o main.o main.cpp

It seems as if there should be another extra step of creating a shared library, but I'm not sure howto. And by the way, is it ok, that I called my object file main.o and not orm or did not give it another name? To some up, my question is how to compile, build shared library and include it in Python (I wish I could use import orm there)?

EDIT

If I do it like so:

// part of main.cpp

BOOST_PYTHON_MODULE( orm ){
    class_<ORM>( "ORM",
    // other code goes here
}

and

$ g++ -I /usr/include/python2.7 -fpic -c -o orm.os main.cpp
$ g++ -o orm.so -shared orm.os -lboost_python -lpython2.7

then I get an error when I try to import it in python:

>>> import orm
...
ImportError: ./orm.so: undefined symbol: _ZNO3.....

So, what am I doing wrong? I hope there is at least one person in the World, who knows the answer.

EDIT

I made another attempt:

$ g++ -fpic -shared -o orm.so main.cpp `pkg-config --cflags --libs python` -I /usr/include/python2.7

And when I do again:

>>> import orm

I still get the same error undefined symbol blablabla. Hope someone knows this sacred knowledge of doing it right.


Solution

  • As requested a tiny working example:

    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
    #include <boost/python.hpp>
    #include <boost/python/raw_function.hpp>
    #pragma GCC diagnostic pop
    
    
    namespace python = boost::python;
    
    class ORM
    {
    public:
      void foo(){std::cout << "foo" << std::endl;}
    };
    
    BOOST_PYTHON_MODULE(orm)
    {
    python::class_<ORM>("ORM")
        .def("foo", &ORM::foo)
    ;
    }
    

    Build command line:

    g++ -I /usr/include/python2.7 -fpic -c -o orm.o orm.cpp
    g++ -o orm.so -shared orm.o -lboost_python -lpython2.7
    

    Running the python module:

    $ python
    Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
    [GCC 4.8.2] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import orm
    >>> o = orm.ORM()
    >>> o.foo()
    foo
    >>> 
    

    If an attempt to import module is returning an undefined symbol error then very likely in runtime there is different version of library being used than the one was used to build the python module. You can use ldd to print shared library dependencies to have a look if everything is ok, for example: ldd orm.so and check if paths to libraries are the same like the ones used for building the module.