Boost.Python is a C++ library which enables interoperability between C++ and Python. Boost.Python is a part of Boost libraries which provides free portable C++ source libraries. The goal of this document is to explain through a simple example how to install and use Boost.Python to connect a C++ library with a Python script.
We will work with the C++ library AddNumbers: AddNumbers.tar.bz2. Read the Create and use static and shared C++ libraries tutorial that explains how to create, compile and link a shared library.
You can download the Boost.Python_AddNumbersClient example: Boost.Python_AddNumbersClient.tar.bz2.
operating system | version |
---|---|
Linux RH Enterprise 4 | kernel 2.6.9-11 |
program | version |
g++ | 3.4.3 |
python | 2.3.4 |
Boost.Jam | 3.1.13-1 |
Boost.Python | 1.33.1 |
These paragraph is intended to help you to install and compile Boost libraries. Refer to the getting started page for more details. The recommended way to build and install the Boost libraries is to use the Boost.Build system. First download and install a prebuilt executable of Boost.Jam which is an extension of the Perforce Jam portable make replacement.
[~/softs/boost-jam] > tar -zxvf boost-jam-3.1.13-1-linuxx86.tgz ... [~/softs/boost-jam] > rm -f boost-jam-3.1.13-1-linuxx86.tgz [~/softs/boost-jam] > mv boost-jam-3.1.13-1-linuxx86 3.1.13-1 [~/softs/boost-jam] > ln -s 3.1.13-1 default
Now download the Boost libraries.
[~/softs/boost] > tar -jxvf boost_1_33_1.tar.bz2 ... [~/softs/boost] > rm -f boost_1_33_1.tar.bz2 [~/softs/boost] > mv boost_1_33_1.tar.bz2 1.33.1 [~/softs/boost] > ln -s boost_1_33_1.tar.bz2 default
Then build and install it using the bjam executable.
[~/softs/boost/1.33.1] > bjam --prefix=${HOME}/softs/boost/1.33.1 --with-python-version=2.3 install
Don't forget to define the BOOST_ROOT environment variable that contains the path to the boost libraries.
[~] > export BOOST_ROOT=${HOME}/softs/boost/default
First let us look furtively the C++ class interface we want to work with.
~/workspace/c++/AddNumbers/inc/AddNumbers.h
#ifndef _ADDNUMBERS_H #define _ADDNUMBERS_H class AddNumbers { private: int _a; int _b; public: AddNumbers (); ~AddNumbers (); void setA (int a); void setB (int b); int getA () const; int getB () const; int getSum () const; }; // AddNumbers #endif // _ADDNUMBERS_H
Now we write a wrapper. See the tutorial introduction for more details. In our example we want to expose some methods to the wrapper.
~/workspace/python/Boost.Python_AddNumbersClient/src/AddNumbers_wrap.cpp
#include "AddNumbers.h" #include <boost/python.hpp> using namespace boost::python; BOOST_PYTHON_MODULE(AddNumbers_wrap) { class_<AddNumbers>("AddNumbers") .def("setA", &AddNumbers::setA) .def("setB", &AddNumbers::setB) .def("getA", &AddNumbers::getA) .def("getB", &AddNumbers::getB) .def("getSum", &AddNumbers::getSum) ; }
Note that we didn't need to expose the default constructor and the destructor of the class. Boost.Python do this work by default. Another important remark is that it is recommended to not use the same name for the Python module name (AddNumbers_wrap) than the class name (AddNumbers). Now compile the wrapper.
[~/workspace/python/Boost.Python_AddNumbersClient] > g++ -I $BOOST_ROOT -I /usr/include/python2.3 \ > -I ../../c++/AddNumbers/inc -fpic -c src/AddNumbers_wrap.cpp -o obj/AddNumbers_wrap.o
And finally link it as a shared library.
[~/workspace/python/Boost.Python_AddNumbersClient] > g++ -shared -L ${BOOST_ROOT}/lib -lboost_python-gcc \ > -L ../../c++/AddNumbers/lib -lAddNumbers -o lib/AddNumbers_wrap.so obj/AddNumbers_wrap.o
Don't forget to add the path of the libAddNumbers.so library to the LD_LIBRARY_PATH environment variable.
[~] > export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${HOME}/workspace/c++/AddNumbers/lib
As an example see the Makefile file in Boost.Python_AddNumbersClient.tar.bz2.
Let's write the following Python script.
~/workspace/python/Boost.Python_AddNumbersClient/src/AddNumbersClient.py
#!/usr/bin/python import sys sys.path.append('lib') import AddNumbers_wrap ab = AddNumbers_wrap.AddNumbers() ab.setA(4) ab.setB(3) print '%d + %d = %d' % (ab.getA(), ab.getB(), ab.getSum())
Then launch it.
[~/workspace/python/Boost.Python_AddNumbersClient] > src/AddNumbersClient.py 4 + 3 = 7
Pyste is a Boost.Python code generator. The user specifies the classes and functions to be exported using a simple interface. Then Pyste parse all the headers and extract the information needed to automatically generate C++ code. To run Pyste we need:
First build and install the Pyste module from the Boost directory.
[~/softs/boost/default/libs/python/pyste/install] > python setup.py build install --prefix=$HOME ...
The module is installed in the Pyste subdirectory of the ${HOME}/lib/python2.3/site-packages directory. It must be accessible through the PYTHONPATH environment variable.
[~] > export PYTHONPATH=${HOME}/lib/python2.3/site-packages
Then dowload the elementtree library.
[~/softs/elementtree] > tar -zxvf elementtree-1.2.6-20050316.tar.gz ... [~/softs/elementtree] > rm -f elementtree-1.2.6-20050316.tar.gz [~/softs/elementtree] > mv elementtree-1.2.6-20050316 1.2.6-src
Now build and install it.
[~/softs/elementtree/1.2.6-src] > python setup.py build install --prefix=$HOME ...
The library is installed in the ${HOME}/lib/python2.3/site-packages/elementtree directory. Its parent directory is already accessible in the PYTHONPATH environment variable. Then download the GCC-XML parser.
[~/softs/gccxml] > tar -zxvf gccxml-0.6.0-x86-linux.tar.gz ... [~/softs/gccxml] > rm -f gccxml-0.6.0-x86-linux.tar.gz [~/softs/gccxml] > mkdir 0.6.0 [~/softs/gccxml] > ln -s 0.6.0 default [~/softs/gccxml] > mv README gccxml-0.6.0-x86-linux-files.tar 0.6.0 [~/softs/gccxml] > cd 0.6.0 [~/softs/gccxml/0.6.0] > tar -xvf gccxml-0.6.0-x86-linux-files.tar ... [~/softs/gccxml/0.6.0] > rm -f gccxml-0.6.0-x86-linux-files.tar
Don't forget to make gccxml accessible in the PATH environment variable.
Pyste inputs interface files to generate C++ code. See the Pyste documentation for more details about creating those interface files. Let us create a such interface file from AddNumbers.h.
~/workspace/python/Boost.Python_AddNumbersClient/int/AddNumbers.pyste
Class("AddNumbers", "AddNumbers.h")
We need only to declare the class AddNumbers that we want to expose to the wrapper. Now we generate the C++ Boost.Python code using the pyste.py script.
[~/workspace/python/Boost.Python_AddNumbersClient] > python ${HOME}/lib/python2.3/site-packages/Pyste/pyste.py \ > --gccxml-path=${HOME}/softs/gccxml/default/bin/gccxml \ > -I ../../c++/AddNumbers/inc --module=AddNumbers_wrap --out=src/AddNumbers_wrap_pyste.cpp int/AddNumbers.pyste
Let us compile the generated C++ wrapper AddNumbers_wrap_pyste.cpp.
[~/workspace/python/Boost.Python_AddNumbersClient] > g++ -I $BOOST_ROOT -I /usr/include/python2.3 \ > -I ../../c++/AddNumbers/inc -fpic -c src/AddNumbers_wrap_pyste.cpp -o obj/AddNumbers_wrap_pyste.o
Then we link the shared library.
[~/workspace/python/Boost.Python_AddNumbersClient] > g++ -shared -L ${BOOST_ROOT}/lib -lboost_python-gcc \ > -L ../../c++/AddNumbers/lib -lAddNumbers -o lib/AddNumbers_wrap.so obj/AddNumbers_wrap_pyste.o
And we execute the python script connected to the wrapper library.
[~/workspace/python/Boost.Python_AddNumbersClient] > src/AddNumbersClient.py 4 + 3 = 7
As an example see the Makefile_pyste file in Boost.Python_AddNumbersClient.tar.bz2. Don't forget to define PYSTEPATH and GCCXMLPATH environment variables before to use the make program.
bjam [option] ... [install|stage]
Boost.Jam is an extension of Perforce Jam portable make replacement. It contains significant improvements made to facilitate its use in the Boost.Build system, but should be backward compatible with Perforce Jam.
option | description |
---|---|
--prefix=PREFIX | Install architecture independent files here. Default on Windows platform: PREFIX=C:\Boost. Default on Unix, Linux: PREFIX=/usr/local. |
--with-python-version=version | Build Boost.Python libraries with the Python version indicated. Default is version=2.4. |
action | description |
install | Builds and installs Boost libraries and headers. |
stage | Builds the Boost libraries and copies them into a common directory. |
pyste [option] ... <interface-file> ...
Pyste is a Boost.Python code generator. It uses the gccxml program to parse all the headers defined in the interface-file files and extract the information needed to automatically generate C++ code.
option | description |
---|---|
--module=<module-name> | The name of the module that will be generated; defaults to the first interface filename, without the extension. |
-I <include-path> | Add an include path. |
--out=<output-file> | Specify output filename (default: <module-name>.cpp). |
--gccxml-path=<gccxml-path> | Path to gccxml executable (default: gccxml). |
link | comment |
---|---|
GNU GCC manual | g++ manual |
Boost.Python library | web site of the Boost.Python library |
Pyste | Boost.Python code generator |
elementtree | elementtree library (needed by Pyste) |
GCC-XML | GCC-XML parser (needed by Pyste) |
Boost libraries | web site of the Boost librairies |