Python and C++ via SWIG

This project gives some example of how python and C++ can be interfaced using SWIG. The idea here is to allow one to write simple classes and functions in C++, and then to have SWIG automatically provide wrappers based on simple naming conventions. NumPy arrays are wrapped with armadillo_ vectors and matrices (sharing the memory) so that they can be modified and used safely.


# Develop your C++ code. # If needed, create a wrapper C++ header for this code using the argument naming

conventions described below to specify their interfaces. This is the code in src/*.hpp here.
# Create a SWIG wrapper that defines the module you want to contain these
functions. This wrapper will typically name the module, include some type conversions and then include the appropriate header files. This is the code in swig/*.i here.
# Edit the Makefile so that it properly generates the wrappers. They go to
_generated/*_wrap.cpp and _generated/py/*.py here.
# Edit to tell python how to build these modules. I.e. add the
appropriate wrapper files to the sources for the extension.

# Include any python support code in the module (mod here). # Make and build the code with:

 python build

The results will go to ``build/lib*/``.  You can ``cd`` to this directory to
try importing and running your modules, or you can ``python install``
to install the compiled modules on your system.

Note: you may need to add the directory with the armadillo_ shared libraries
to your ``LD_LIBRARY_PATH`` in order for python to find them.  This is
`not ideal`_, but I do not know of a better solution.  (One option is to link
this into a common place, and wrap the python executable in a local
environment that sets ``LD_LIBRARY_PATH``.)

The Build Process

The build process consists of two steps:

# Generating the *_wrap.cpp files using swig # Compiling these and installing the python modules.

In principle, these could both be done with, but this requires some hacking (see the open tickets listed at the end). Thus, the recommended way is to use a tool like make to perform the first step, and then let do the final building, and we take this approach here. The Makefile here is kept simple to demonstrate usage: it does not properly track dependencies etc.


The raw files here consist of:

C++ source files defining the classes and functions.
SWIG interface file defining the modules. Ideally these will just define the typemaps required so that the interface can be deduced automatically, but this is a little incomplete right now.
swig/numpy.i, swig/pyfragments.swg:
SWIG interface files defining NumPy typemaps and associated fragments. These come from the numpy doc directory. (They hope it will be eventually included with SWIG.)
SWIG interface that defines typemaps for armadillo_ matrices and vectors. By providing types like mat_OUT, we can specify input and output arguments directly in the source file, eschewing the need for detailed specifications in the module *.i file.
Python package with pure python sources that will form the base package. This should also have mod/ defined which might want to from swig import *.

The Makefile is responsible for calling swig and generating:

_generated/*_wrap.cpp: _generated/py/*.py: _generated/py/

The python build_ext process will then compile these files:

Compiled extension module.

Finally, the python build process (which will call build_ext first if needed) will install everything into the build directory under something like:


In order to get everything in there properly I needed to do the following in

  • Name the extension mod.swig._*. This makes sure that it gets put in the correct place. Note the convention for included an underscore before the module name.
  • Include packages = ["mod", "mod.swig"]: This includes both the pure python stuff in mod as well as the generated stuff.
  • Include package_dir = {"mod.swig": "_generated/py"]: This tells distutils that the generated package _generated/py should be remapped to mod.swig. Note that this requires _generated/py to be a package, which is why make had to generate the _generated/py/ files.


The SWIG support built into distutils is not ideal as pointed out by these tickets (open as of 23 May 2012):