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.