Extend Your Scripting Language with SWIG

SWIG makes it easy to write an extension for your favorite scripting language (or languages). Learn how it works.

Modern scripting languages combine the best features of compiled languages with the immediacy of interpreted languages. For instance, Python and Ruby have a rich object model, yet require no compilation. You can write and execute an entire program right from the command-line.

However, the rise of scripting languages cannot be attributed solely to instant gratification. Instead, much of the rapid adoption and ultimate success must be credited to extensibility. As Allison Randal points out in her feature story Why Parrot is Important, a new language cannot be popularized if it lacks modern features, including string functions, connectivity, regular expressions, and APIs to system calls. Extensions to the core language legitimize a language and bolster its prowess. For example, Python is popular among math geeks because a myriad of extensions are available to the trade.

Most language extensions are developed in the language itself. For instance, PHP’s connectivity features are high-level abstractions and amalgams of the socket_ primitives.

Other extensions marry a language to a C library. Indeed, PHP’s socket_ calls are thin wrappers around the equivalent functions and system calls found in libc. Many of Python’s math extensions, too, are facades of highly-optimized and specialized libraries. There are real advantages to C extensions. The bulk of the code lay close to bare metal; existing code need not be rewritten; and legacy and proprietary code can be repurposed, too.

However, and Parrot extensions aside, there is still a good amount of work required to make an extension available to multiple scripting languages. Ruby’s extension paradigm differs from Python’s, which differs from Perl’s. If you write low-level C code, you can expect to work hard to integrate your API with all the popular interpreters.

Or, like a smart programmer, you can be lazy and turn to the Simplified Wrapper and Interface Generator. SWIG automatically generates code to connect C (and C++) code to scripting languages. The list of supported scripting languages is quite long: Ruby, Python, Perl, PHP, Guile, and Tcl. (SWIG also generates code for compiled languages, but those are ignored here.)

To write an extension with SWIG, you write and validate your C code separately, create an interface definition in SWIG’s own syntax, generate some glue code, and compile. That’s all there is to it. Better yet, you can generate glue for one or more languages from the same interface (or similar interfaces) and create an extension suitable for each language.

Like most open source software, SWIG is available as source code or as a pre-built package. If you have a Mac or Windows computer, you must build from source. The latest version of SWIG is 1.3.39 dated March 21, 2009, and is suitable for the latter two platforms and all Unix variants. Building the source is easy: download the code, unpack it, run ./configure and make.

$ wget 'http://downloads.sourceforge.net/sourceforge/\
  swig/swig-1.3.39.tar.gz?use_mirror=internap'
$ tar xvzf swig-1.3.39.tar.gz
$ cd swig-1.3.39
$ ./configure
$ make
$ sudo make install

If you use Debian or Ubuntu, you can use apt-get to install SWIG immediately.

$ sudo apt-get install swig1.3  swig1.3-examples, swig1.3-docent

The install adds the eponymous utility swig. Type swig -help to see a list of options and usage hints.

In addition to SWIG, you may need to download the header files for Python and Ruby, if you did not build those interpreters from scratch. The header files are necessary to build extensions for each of those languages. Again, apt-get can help.

 $ sudo apt-get install python-dev ruby-dev
 

A Simple Example

Let’s begin with a simple example found in the SWIG documentation. A novel example follows momentarily.

This C code…

int fact(int n) {
  if (n <= 1)
    return 1;
  else
    return n * fact(n-1);
}

… produces n! given integer n.

To provide fact() to Perl, say, you specify an interface with SWIG, generate the glue suitable for Perl, and compile and load the extension. Here’s the SWIG code.

%module myfact

%{
  #include "EXTERN.h"
  #include "perl.h"
  #include "XSUB.h"

  extern int fact(int n);
%}

extern int fact(int n);

The %module parameter assigns a proper name to the module. This is the name you use in your Perl script. The declarations between %{ and %} are included at the start of the glue file. Perl extensions built with SWIG must include the three files shown. The last declaration is used as the basis for the name of the wrapper function.

Put the C code in myfact.c and the SWIG code in myfact_perl.i. Next, run SWIG to create the wrapper code and the Perl code required to use the extension.

$ swig -perl5 myfact_perl.i

As you might guess, the -perl5 option causes SWIG to create Perl 5-compatible code. Specifically, the -perl5 option creates two files: myfact_wrap.c, the wrapper for the C code, and myfact.pm, a Perl module. The last step is to compile and craft the extension as a shared library.

$ gcc -c -fpic -Dbool=char myfact.c myfact_perl_wrap.c \
  -D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS \
  -DDEBIAN -fno-strict-aliasing -pipe -isystem /usr/local/include \
  -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/lib/perl/5.8/CORE
$ gcc -shared *.o -o myfact.so

(The rather long list of options to the compiler in the compile step is highly machine-dependent. To find the options suitable for your system, build SWIG from source code as instructed above, go to the Examples/perl5 directory, type make, and make a note of the options used to build the sample extension.

Now the extension is ready to use with Perl.

$ perl
use myfact;
print myfact::fact(5);
print;
^D
120

And with only minor alterations, the same extension can be rebuilt to use with Python. Here is myfact_python.i, which is minimal as compared to the Perl equivalent.

%module myfact

%{
  extern int fact(int n);
%}

extern int fact(int n);

Compilation is also simpler.

$ rm *.o *.so
$ swig -python myfact_python.i
$ gcc -c -fpic  myfact_python_wrap.c myfact.c \
  -I/usr/include/python2.5 -I/usr/lib/python2.5/config
$ gcc -shared  *.o -o _myfact.so

Now the same code is usable with Python.

>>> import myfact
>>> print myfact.fact(4)
24
>>> quit()

Comments on "Extend Your Scripting Language with SWIG"

x95tobos

As a zero experience programmer/user in this game of interfacing with C/C++, my 2 cents: sometimes you need to work hard and integrate at low level (real-time/embedded systems, to squize most of the juice out of limited hardware, etc).

Or be lazy and go the API calls way, as suggested here. Your main gain is probably you will end up employing less demanding developers, that you will pay much less. Then again, what you pay is what you get.

Reply

You, are you looking for? .. See Qiang head down, do not come in words, that police are afraid, at the moment his family did not get the message, while hospitals and messy Cao Cao, to know not only shootings wound their two policemen.

Reply

Leave a Reply to x95tobos Cancel reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>