Categories
blog

SWIG and Python anguish

This post may be useful if: you want to have a c++ program that runs a python script that calls some c++ functions or you want to pass objects between c++ and python, and you are trying to figure out how to do this with SWIG.

The last 6 or so working hours I have been in a small nightmare, full of “SWIG_” prefixed variables and much woe. My software, SDS, simulates the actions of many cells as they co-operate to build some interesting forms. So far, the cells run a program written in vanilla c++ (Mmm … vanilla), which has meant two things:

  1. I build meta-program, called names like “LimbGrowth” that accepts a number of parameters, like rate of growth. These parameters are specified using a config file, written by the user (in libconfig format.)
  2. Whenever I want to try a new idea, I have to write the parameterised C++ version and recompile the whole system, making sure that the various shared libraries are copied around to the right places.

Recently I have thought about opening up the cell logic completely to the user, through some sort of scripting language. This is where my headache began. After trying to compile chaiscript (“Easy to use scripting for C++”) and failing, I decided to try embedding Python. This made a lot of sense as the Blender interface to SDS is also written in Python, and so we (BV and me) have already “extended” Python to use SDS. “Embedding” python goes the other way, my C++ code would then be able to run Python scripts.

Enter SWIG. This is a tool that generates the “glue” that allows Python and C++ to talk — in both directions. BV used SWIG so that Python could talk to SDS. I needed to use SWIG so that SDS could speak Python. The subtleties of platforms, swig versions, and lack of documentation meant that creating a trivial “hello world” took much longer than it should have. No further ado is required, my successful code is here: http://hg.bp.io/public/misc/pyembed/

The code runs under MingW and uses the latest Swig (2.0.0). There are three examples in the repository:

  1. Test1 is a c++ program that runs a python program that calls a c++ function,
  2. Test2 is a c++ program that calls a python function that uses a static variable to pass an object pointer from c++ to python, and
  3. Test3 is a c++ program that calls a python function and passes it a pointer to a c++ object.

This was harder than it should have been, but hopefully my code will help anyone who was in a similar situation. I would be unsurprised to hear that it doesn’t work under Linux, Mac, different versions of Python (I used 2.6) or swig. Right now, I will stick with SWIG, but I’m not sure that it is the best tool for the job. Maybe ctypes would be better…