Boost and Python 3.x

Yes this question is super old, but I had to do something that wasn't specified in any of the answers here (though it was built off some of the suggestions), so I'll quickly jot down my entire process:

  1. Download boost_X_Y_Z.tar.bz2 (I used boost 1.68.0)
  2. tar --bzip2 -xf boost_1_68_0.tar.bz2 (where you want folder to be temporarily)
  3. cd boost_1_68_0
  4. ./bootstrap.sh --with-python-version=3.6 --prefix=/usr/local
  5. ./b2
  6. sudo ./bjam install
  7. cp tools/build/example/user-config.jam $HOME, then modify the contents of this file to say using python : 3.6 : /usr/bin/python3 : /usr/include/python3.6m : /usr/lib ; (or whatever folders are appropriate for your environment)

Given this C++ source file BoostPythonHelloWorld.cpp:

#include <boost/python.hpp>

char const* say_hi()
{
    return "Hi!";
}

BOOST_PYTHON_MODULE(BoostPythonHelloWorld)
{
    boost::python::def("say_hi", say_hi);
}

And this Python script BoostPythonHelloWorld.py:

import BoostPythonHelloWorld
print(BoostPythonHelloWorld.say_hi())

It can be compiled and ran as such:

gcc -c -fPIC -I/path/to/boost_1_68_0 -I/usr/include/python3.6 /other_path/to/BoostPythonHelloWorld.cpp
gcc -shared -Wall -Werror -Wl,--export-dynamic BoostPythonHelloWorld.o -L/path/to/boost_1_68_0/stage/lib -lboost_python36 -o BoostPythonHelloWorld.so
python3 BoostPythonHelloWorld.py

The part that was different for me was -Wl,--export-dynamic BoostPythonHelloWorld.o, I had not seen that anywhere else, and I was getting a Python error concerning an undefined symbol until I added that.

Hope this helps someone down the line!


Newer versions of Boost should work fine with Python V3.x. This support has been added quite some time ago, I believe after a successful Google Summer of Code project back in 2009.

The way to use Python V3 with Boost is to properly configure the build system by adding for instance:

using python : 3.1 : /your_python31_root ;

to your user-config.jam file.


libboostpython needs to be built with python3 in order to do this. This doesn't work with boost 1.58 (which comes with Ubuntu 16.04), so make sure you download the latest boost distribution. I just did this with boost_1_64_0.

As mentioned above, find the file "user-config.jam" in you boost code distribution, and copy it to $HOME.

cp /path/to/boost_1_64_0/tools/build/example/user-config.jam $HOME

Then edit the python line (the last line) so that is says:

using python : 3.5 : /usr/bin/python3 : /usr/include/python3.5m : /usr/lib ;

This is correct for Ubuntu 16.04. You can use pkg-config to find the correct include directory.

user@computer > pkg-config --cflags python3
-I/usr/include/python3.5m -I/usr/include/x86_64-linux-gnu/python3.5m

And you only need the first include directory.

Then build boost from scratch. (Sorry.) I install it to /usr/local

cd /path/to/boost_1_64_0
./bootstrap.sh --prefix=/usr/local
./b2 
sudo ./b2 install

Now jump into the python example directory, and build the tutorial

cd /path/to/boost_1_64_0/libs/python/example/tutorial
bjam

This will not build correctly if you have a system install of boost, because, under the hood, bjam is linking to libboostpython using the g++ parameter "-lboost". But, on Ubuntu 16.04, this will just go and find "/usr/lib/x86_64-linux-gnu/libboost_python-py27.so.1.58.0", and then the python bindings will fail to load. In fact, you'll get his error:

ImportError: /usr/lib/x86_64-linux-gnu/libboost_python-py27.so.1.58.0: undefined symbol: PyClass_Type

If you want to see the g++ commands that bjam is using, do this:

user@computer > bjam -d2 -a | grep g++
g++  -ftemplate-depth-128 -O0 -fno-inline -Wall -g -fPIC -I/usr/include/python3.5m -c -o "hello.o" "hello.cpp"
g++ -o hello_ext.so -Wl,-h -Wl,hello_ext.so -shared -Wl,--start-group hello.o  -Wl,-Bstatic  -Wl,-Bdynamic -lboost_python -ldl -lpthread -lutil -Wl,--end-group

Here we see the problem, you need "-L/usr/includ/lib" just before "-lboost_python". So execute this to link the shared library correctly:

g++ -o hello_ext.so -Wl,-h -Wl,hello_ext.so -shared -Wl,--start-group hello.o  -Wl,-Bstatic  -Wl,-Bdynamic -L/usr/local/lib -lboost_python -ldl -lpthread -lutil -Wl,--end-group

You may need to rerun ldconfig (or reboot)

sudo ldconfig

And you are finally ready to go:

user@computer > python3
Python 3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import hello_ext
>>> hello_ext.greet()
'hello, world'
>>> exit()