Sunday, March 10, 2013

using SWIG to connect python and a c++ dll

Although I am a great fan of Cython when you already have a class defined in C++ code you do not want to rewrite it for Cython. Already a long time ago I once used SWIG to create a link between C++ classes and python. This is fairly easy as long as you have clear interface functions which you can use to pass data to and from your class. Nevertheless, it took me some effort to get things running for my new class.

Following the SWIG tutorial I started with something like this myExample.i
%module myExample
 %{
 /* Includes the header in the wrapper code */
 #include "myModule.h"
 #include "myModule2.h"
 %}
 
 /* Parse the header file to generate wrappers */
 #include "myModule.h"
 #include "myModule2.h"

After compiling this I got a module that I could import in Python. However, the module did not contain the classes I had defined in my C++ code. Because there are not so many clear examples of SWIG and C++ I could not really find an explanation for this. Only after recreating the exact example of the tutorial (using copy/paste from the web) I found that I made a simple typing error: the #include in the second part of the myExample.i should be %include!

%module myExample
 %{
 /* Includes the header in the wrapper code */
 #include "myModule.h"
 #include "myModule2.h"
 %}
 
 /* Parse the header file to generate wrappers */
 %include "myModule.h"
 %include "myModule2.h"

Now everything works nicely. Compiling is not very difficult. I have setup a Makefile for this:

CPP=g++

CFLAGS=  -Wunused  -O3

PYTH_INCL = /c/Python27/include
PYTH_LIB = /c/Python27/Libs

PYLIB = -lpython27

OBJS= myModule.o
modOBJS= myModule2.o
SRC_DIR = ..
all: myExample_mod

myExample_mod: $(modOBJS) myExample.i
 swig -I.. -python -c++ -shadow myExample.i
 $(CPP) -I$(PYTH_INCL) $(INCLUDE) -c myExample_wrap.cxx
 $(CPP) -shared -L$(PYTH_LIB) myExample_wrap.o $(OBJS) $(PYLIB) $(LIBS) -o _myExample.pyd

%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h
 $(CPP) -c $(CFLAGS) $(INCLUDE)  $< -o $@
With this Makefile you can use import myExample in your python code to import the module. Thus far I have only used simple interface methods in my classed that work with integers and floats as input and output variables. This makes communication between the module and python very simple (no special effort seems to be required). I assume that if you want to pass arrays, strings, etc. things will become more difficult.

No comments:

Post a Comment