SWIG: Simplified Wrapper and Interface Generator

SWIG allows you to access the flexibility of lower level C/C++ code through more convenient and higher level languages such as Python, Java, etc.. In KUSP, we primarily use SWIG in combination with the CMake Python-Distutils to automatically create and package generated Python wrappers for our C user-space libraries.

Contents:

How SWIG Works

You first must have some existing C/C++ code that you wish to use with a different language. From there it is easiest if you have a header file that defines all of the function prototypes from the C/C++ code that you wish to use. If there is not one, I would suggest making one for ease of use.

From the header file you then must make a swig interface (.i) file that defines the functions you wish to wrap. In my experience, it has been that this is normally just a modified copy of the previously mentioned header file of the code that you wish to use. After creating the interface file is when you execute SWIG:

bash> cd <path-to-source>
bash> swig -<wrap-language> <module-name>.i

This creates a file <module-name>_wrap.c and another for the language that you have chosen (i.e. <module-name>.py or <module_name>.java). This <module-name>_wrap.c file now needs to be compiled into a shared library to be used for the wrapper module:

bash> gcc -c <module-name>.c <module-name>_wrap.c -I<path-to-wrap-language-headers>
bash> ld -shared <module-name>.o <module-name>_wrap.o -o _<module-name>.so

Now you should be able to use the created wrapper and access the C code. This is very simple and can be extrodinarily helpful since you do not have to write the wrappers by hand, and is easily automoized. If you change the code in the C source file then it is normally trivial to tweak to the interface file and rebuild a new wrapper.

Python Wrappers by Hand

It is easiest to demonstrate the use of SWIG through a simple by hand example. Presume that there is an existing C library with a few different subroutines that you would like to call in a Python program that you are creating.

swig_demo.h:

extern int two_plus_number(int number);
extern int print_message(int message_code);

swig_demo.c:

#include <stdlib.h>
#include <stdio.h>
#include "swig_demo.h"

/* Adds two to a number and returns the result. */
extern int two_plus_number(int number){

    return 2+number;
}

/* Prints a message from The Wizard of Oz
   based on message_code mod 2. It prints
   the message and returns the value of the
   message_code mod 2. */
extern int print_message(int message_code){

    int decoded_message = message_code%2;

    switch(decoded_message){
        case 0:
            printf("I\'ll get you my pretty and your little dog too!\n");
        break;
        case 1:
            printf("You are talking to a man who has laughed in ");
            printf("the face of death, sneered at doom and ");
            printf("chuckled at catastrophe.\n");
        break;
        default:
            printf("Toto, we\'re not in Kansas any more!");
        break;
    }

    return decoded_message;

}

To create a Python module that will be able to call these useful C functions, you will first need to create the SWIG interface file. They follow the convention of:

/* I am a comment about <name-of-module>.i. */
%module <name-of-wrapper>
%{
# function declarations ( or header files here ).
%}

/* If you used function declarations above, just
 copy and past the function declarations that you
 used above. If you used headers, place the
 function definitions that you want from
 those headers here. */

As a special note, the function declarations should all start with extern.

So to create the interface file for swig_demo we need to make a new file swig_demo.i.

swig_demo.i:

/* swig_demo.i */
%module swig_demo
%{
extern int two_plus_number(int number);
extern int print_message(int message_code);
%}

extern int two_plus_number(int number);
extern int print_message(int message_code);

After creating swig_demo.i we now can run swig:

bash> swig -python swig_demo.i

This step creates the python wrapper swig_demo.py. This will also create a new SWIG generated code file named swig_demo_wrap.c that you will need to compile along with the original C code in order to make a proper wrappable library, thus allowing the swig_demo.py to function correctly. To do this use gcc to compile them both making sure to include headers if they are in separate directories and Python headers:

bash> gcc -c swig_demo.c swig_demo_wrap.c \
        -I/usr/include/python<your-python-version>
bash> ld -shared swig_demo.o swig_demo_wrap.o -o _swig_demo.so

Great, you should now be able to use your wrapper as a normal import in Python, an example using the Python interpreter:

bash> python

Python 2.6 (r26:66714, Jun  8 2009, 16:07:26)
[GCC 4.4.0 20090506 (Red Hat 4.4.0-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import swig_demo
>>> retval = swig_demo.two_plus_number(23)
>>> print retval
25
>>> swig_demo.print_message(42)
I'll get you my pretty and your little dog too!
0
>>> swig_demo.print_message(41)
You are talking to a man who has laughed in the face of death,
sneered at doom and chuckled at catastrophe.
1

SWIG + CMake + Distutils

TODO.D

Indices and tables

Table Of Contents

This Page