SWIG Tutorial

<p>
<img src="images/tutorial.png">

<p>
So you want to get going in a hurry?  To illustrate the use of SWIG,
suppose you have some C functions you want added to Tcl, Perl, Python, Java and C#.
Specifically, let's say you have them in a file 'example.c'

<ul><tt><pre>
/* File : example.c */

#include &lt;time.h&gt;
double My_variable = 3.0;

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

int my_mod(int x, int y) {
    return (x%y);
}
	
char *get_time()
{
    time_t ltime;
    time(&amp;ltime);
    return ctime(&amp;ltime);
}

</pre></tt></ul>

<h3>Interface file </h3>

Now, in order to add these files to your favorite language, you need to write an
"interface file" which is the input to SWIG.  An interface file for these
C functions might look like this :

<ul><tt><pre>
/* example.i */
%module example
%{
/* Put header files here (optional) */
%}

extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
</pre></tt></ul>

<h3> Building a Tcl module </h3>

At the UNIX prompt, type the following (shown for Linux, see the <a href="http://swig.cs.uchicago.edu/cgi-bin/wiki.pl?SwigFaq/SharedLibraries">SWIG Wiki Shared Libraries</a> page for help with other operating systems):

<blockquote>
<pre><tt>
unix % swig -tcl example.i
unix % gcc -fpic -c example.c example_wrap.c \
       -I/usr/local/include 
unix % gcc -shared example.o example_wrap.o -o example.so
unix % tclsh
% load ./example.so example
% puts $My_variable
3.0
% fact 5
120
% my_mod 7 3
1
% get_time
Sun Feb 11 23:01:07 1996

% 
</tt></pre></blockquote>

The <tt> swig </tt> command produces a file <a href = "tutorial/example_wrap.html">
<tt> example_wrap.c </tt> </a> that should be compiled and linked with
the rest of the program.  In this case, we have built a dynamically 
loadable extension that can be loaded into the Tcl interpreter using
the 'load' command.   

<h3> Building a Python module </h3>

Turning C code into a Python module is also easy.  Simply do the following (shown for Irix, see the <a href="http://swig.cs.uchicago.edu/cgi-bin/wiki.pl?SwigFaq/SharedLibraries">SWIG Wiki Shared Libraries</a> page for help with other operating systems):

<blockquote> <tt> <pre>

unix % swig -python example.i
unix % gcc -c example.c example_wrap.c \
       -I/usr/local/include/python2.1
unix % ld -shared example.o example_wrap.o -o _example.so 
</pre> </tt> </blockquote>

We can now use the Python module as follows : 
<blockquote> <tt> <pre>
>>> import example
>>> example.fact(5)
120
>>> example.my_mod(7,3)
1
>>> example.get_time()
'Sun Feb 11 23:01:07 1996'
>>>
</pre>
</tt> </blockquote>

<h3> Building a Perl module </h3>
You can also build a Perl5 module as follows (shown for Solaris, see the <a href="http://swig.cs.uchicago.edu/cgi-bin/wiki.pl?SwigFaq/SharedLibraries">SWIG Wiki Shared Libraries</a> page for help with other operating systems):

<blockquote><tt><pre>
unix % swig -perl5 example.i
unix % gcc -c example.c example_wrap.c \
       -I/usr/lib/perl/solaris/5.003/CORE 
unix % ld -G example.o example_wrap.o -o example.so
unix % perl
use example;
print $example::My_variable,"\n";
print example::fact(5),"\n";
print example::get_time(),"\n";
&lt;ctrl-d&gt;
3.0
120
Sun Feb 11 23:01:07 1996
unix % 
</pre></tt></blockquote>

<h3> Building a Java module </h3>
SWIG will also generate JNI code for accessing C/C++ code from Java. Here is an example building a Java module (shown for Cygwin, see the <a href="http://swig.cs.uchicago.edu/cgi-bin/wiki.pl?SwigFaq/SharedLibraries">SWIG Wiki Shared Libraries</a> page for help with other operating systems):

<blockquote><tt><pre>
$ swig -java example.i
$ gcc -c example.c example_wrap.c -I/c/jdk1.3.1/include -I/c/jdk1.3.1/include/win32
$ gcc -shared example.o  example_wrap.o -mno-cygwin -Wl,--add-stdcall-alias  -o example.dll
$ cat main.java
public class main {
  public static void main(String argv[]) {
    System.loadLibrary("example");
    System.out.println(example.getMy_variable());
    System.out.println(example.fact(5));
    System.out.println(example.get_time());
  }
}
$ javac main.java
$ java main
3.0
120
Mon Mar  4 18:20:31  2002
$
</pre></tt></blockquote>

<h3> Building a C# module </h3>
SWIG will also generate code for accessing C/C++ code from C# using PInvoke. Here is an example building a C# module (shown for Linux, see the <a href="http://swig.cs.uchicago.edu/cgi-bin/wiki.pl?SwigFaq/SharedLibraries">SWIG Wiki Shared Libraries</a> page for help with other operating systems). It uses the open source <a href="http://www.southern-storm.com.au/portable_net.html">DotGNU Portable.NET</a> C# compiler which runs on most Unix systems, but works equally well using other C# compilers:

<blockquote><tt><pre>
$ swig -csharp  example.i
$ gcc -c -fpic  example.c example_wrap.c
$ gcc -shared example.o  example_wrap.o   -o libexample.so
$ cscc -o runme *.cs
$ cat runme.cs
using System;
public class runme {
    static void Main() {
        Console.WriteLine(example.My_variable);
        Console.WriteLine(example.fact(5));
        Console.WriteLine(example.get_time());
    }
}
$ ilrun runme
3
120
Tue May 13 10:45:45 2003

$
</pre></tt></blockquote>

<h3> SWIG for the truly lazy </h3>

As it turns out, it is not always necessary to write a special interface
file.  If you have a header file, you can often just include it directly in the
SWIG interface. For example:

<blockquote>
<tt> <pre>
%module example
%{
/* Includes the header in the wrapper code */
#include "header.h"
%}

/* Parse the header file to generate wrappers */
%include "header.h"
</pre></tt>
</blockquote>

Alternatively, some people might just include SWIG directives in a header
file with conditional compilation.  For example:

<blockquote>
<pre>
#ifdef SWIG
%module example
%{
#include "header.h"
%}
#endif

extern int fact(int n);
...
</pre>
</blockquote>

<h3> Running SWIG under Microsoft Windows </h3>

SWIG also works perfectly well under all known 32 bit versions of
Windows including 95/98/NT/2000/XP.  SWIG is typically invoked from
the command prompt and can be used with NMAKE.  Modules are typically
compiled in the form of a DLL that can be dynamically loaded into Tcl,
Python, or whatever language you are using.  With a little work, SWIG
can also be used as a custom build option within MS Developer Studio.

<h3>That's it (well, more or less)</h3>

That's about everything you need to know to get started. Here's the short checklist :

<ul>
<li> Make sure you specify a module name.
<li> Use ANSI C/C++ syntax
<li> Figure out how to compile a shared library module / dynamic link library (may require reading a few man 
pages for your compiler).
<li> Relax.
</ul>

<h3>Surely there's more to it...</h3>

The above example is intentionally simple, but the general idea
extends to more complicated C/C++ programming tasks.  In fact, it is
important to know that SWIG is a fairly complete C++ compiler with
support for nearly every language feature.  This includes
preprocessing, pointers, classes, inheritance, and even C++ templates.
SWIG can also be used to package structures and classes into proxy
classes in the target language---exposing the underlying functionality in a very
natural manner.

<p>
To illustrate, suppose you wanted to wrap the following C++ data structure:

<blockquote>
<pre>
// pair.h.  A pair like the STL
namespace std {
   template&lt;class T1, class T2&gt; struct pair {
       T1 first;
       T2 second;
       pair() : first(T1()), second(T2()) { };
       pair(const T1 &f, const T2 &s) : first(f), second(s) { }
   };
}
</pre>
</blockquote>

To wrap with SWIG, you might specify the following interface:

<blockquote>
<pre>
// pair.i - SWIG interface
%module pair
%{
#include "pair.h"
%}

// Ignore the default constructor
%ignore std::pair::pair();      

// Parse the original header file
%include "pair.h"

// Instantiate some templates

%template(pairii) std::pair&lt;int,int&gt;;
%template(pairdi) std::pair&lt;double,int&gt;;
</pre>
</blockquote>

Now, compiling (Python):

<blockquote>
<pre>
$ swig -python -c++ pair.i
$ c++ -c pair_wrap.c -I/usr/local/include/python2.1
$ c++ -shared pair_wrap.o -o paircmodule.so
$ python
Python 2.1 (#3, Aug 20 2001, 15:41:42) 
[GCC 2.95.2 19991024 (release)] on sunos5
Type "copyright", "credits" or "license" for more information.
>>> import pair
>>> a = pair.pairii(3,4)
>>> a.first
3
>>> a.second
4
>>> a.second = 16
>>> a.second
16
>>> b = pair.pairdd(3.5,8)
>>> b.first
3.5
>>> b.second
8
</pre>
</blockquote>

