Swig seems to be the most popular method for wrapping C++ with Python. I’m using Boost Python however, as I think it fits better with the software I’m trying to wrap, Chaste.

Installing pyplusplus

A quick google suggests that pyplusplus is the way to go for automatic wrapper generation with Boost Python. It relies on gccxml to make an xml representation of the contents of the cpp source files and pygccxml to get at the contents of the xml with a Python interface. Sadly, it seems that the original incarnations of these projects are dead.

gccxml has recently been replaced with castxml, which is maintained by Kitware for ITK wrapping. pygccxml has also been revived as part of the same project The ‘official’ version of pyplusplus doesn’t seem to support the new pygccxml. However there is a version maintained by the Open Motion Planning Library that is more up-to-date. I couldn’t get it to work with the latest pygccxml (1.7.6), but it works fine with an older version (1.7.2).

So, to get started with pyplusplus do (linux):

pip install pygccxml==1.7.2

Troubleshooting castxml

For some Debian/Ubuntu installations there is a castxml distribution which is some form of wrapper over the older gccxml. This is not supported by the newer pygccxml and for me led to errors related to not supporting c++11.

There is a standlone binary of the proper castxml which can be downloaded as described here. I found the default clang compiler in the binary had problems with Boost. It can be directed to use a gcc compiler instead by doing:

castxml --castxml-cc-gnu /path/to/gcc --castxml-gccxml -o output_file

Using pyplusplus

The official pyplusplus examples mostly work, however I needed to explicitly tell the module_builder where castxml was to prevent the system version from being used and had to pass in the compiler options to use gcc.

from pyplusplus import module_builder
from pygccxml import parser

includes = ["list_of_include_dirs"]
header_collection = ["list_of_header_dirs"]
generator_path = "path/to/castxml"
generator_name = "castxml"
xml_generator_config = parser.xml_generator_configuration_t(xml_generator_path=generator_path, 
                                                            compiler = "gnu",

builder = module_builder.module_builder_t([header_collection],
                                            xml_generator_path = generator_path,
                                            xml_generator_config = xml_generator_config,
                                            include_paths = includes)


comments powered by Disqus