1 Introduction

What is SWIG?

SWIG is a software development tool that simplifies the task of interfacing different languages to C and C++ programs. In a nutshell, SWIG is a compiler that takes C declarations and creates the wrappers needed to access those declarations from other languages including including Perl, Python, Tcl, Ruby, Guile, and Java. SWIG normally requires no modifications to existing code and can often be used to build a usable interface in only a few minutes. Possible applications of SWIG include:

SWIG was originally designed to make it extremely easy for scientists and engineers to build extensible scientific software without having to get a degree in software engineering. Because of this, the use of SWIG tends to be somewhat informal and ad-hoc (e.g., SWIG does not require users to provide formal interface specifications as you would find in a dedicated IDL compiler). Although this style of development isn't appropriate for every project, it is particularly well suited to software development in the small; especially the research and development work that is commonly found in scientific and engineering projects.

Why use SWIG?

Although C is great for high-performance number crunching and systems programming, trying to make an interactive and highly flexible C program is a pain. Even though it is possible to build a user interface using command line options, a home grown command interpreter, or a graphical user interface, this often results in a program that is hard to extend, hard to modify, hard to port between platforms, and hard to use. Furthermore, this sort of activity wastes a lot of development time because it usually diverts everyone's attention away from the real problem that they're trying to solve.

Many of the problems with C are due to the way in which many programs are organized. For example, a lot of programs are structured as follows:

In this case, the main() program may read command line options or simple commands from stdin. However, modifying or extending the program to do something new requires changing the C code, recompiling, and testing. If you make a mistake, you need to repeat this cycle until things work. Of course, as more and more features are added, the program usually turns into a horrible mess that is even more difficult to modify than before (although this undoubtedly increases the job security of the programmer).

A common mistake is to assume that all of the problems with C can somehow be fixed by using a better C---perhaps an undebuggable language with unreadable syntax, complicated semantics, and nearly infinite compilation time. This is an unfortunate.

Perhaps a better approach is to place your application under the control of a very high-level language such as a common scripting language interpreter. High level languages excel at turning hard problems into easy tasks. They also provide a nice framework for managing software components and gluing different systems together. Not only that, they make it easy for users to configure the software to their liking and to program it to perform new tasks without ever having to touch a C/C++ compiler.

SWIG simplifies the task of incorporating C++ code into a high-level programming environment. Specifically, rather than creating a huge monolithic package, SWIG allows you to restructure your application as a collection of functions and variables that can be accessed from the convenience of a high-level language. With this model, all of the functionality of your C program is retained. The only difference is that the high-level program logic and control is now driven by the high-level language instead of a low level main() function.

SWIG tries to make the integration between scripting languages and C as painless as possible. This allows you to focus on the underlying C program and using the high-level scripting language interface, but not the tedious and complex chore of making the two languages talk to each other.

A SWIG example

The best way to illustrate SWIG is with a simple example. Consider the following C code:

/* File : example.c */

double  My_variable  = 3.0;

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

/* Compute n mod m */
int my_mod(int n, int m) {
	return(n % m);
}

Suppose that you wanted to access these functions and the global variable My_variable from Tcl. You start by making a SWIG interface file as shown below (by convention, these files carry a .i suffix) :

SWIG interface file

/* File : example.i */
%module example
%{
/* Put headers and other declarations here */
%}

extern double My_variable;
extern int    fact(int);
extern int    my_mod(int n, int m);

The interface file contains ANSI C function prototypes and variable declarations. The %module directive defines the name of the module that will be created by SWIG. The %{,%} block provides a location for inserting additional code such as C header files or additional C declarations.

The swig command

SWIG is invoked using the swig command. We can use this to build a Tcl module (under Linux) as follows :

unix > swig -tcl example.i
Generating wrappers for Tcl.
unix > gcc -c -fpic 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
% fact 4
24
% my_mod 23 7
2
% expr $My_variable + 4.5
7.5
%

The swig command produced a new file called example_wrap.c that should be compiled along with the example.c file. Most operating systems and scripting languages now support dynamic loading of modules. In our example, our Tcl module has been compiled into a shared library that can be loaded into Tcl. When loaded, Tcl can now access the functions and variables declared in the SWIG interface. A look at the file example_wrap.c reveals a hideous mess. However, you almost never need to worry about it.

Building a Perl5 module

Now, let's turn these functions into a Perl5 module. Without making any changes type the following (shown for Solaris):

unix > swig -perl5 example.i
Generating wrappers for Perl5
unix > gcc -c example.c example_wrap.c \
	-I/usr/local/lib/perl5/sun4-solaris/5.003/CORE
unix> ld -G example.o example_wrap.o -o example.so 								# This is for Solaris
unix > perl5.003
use example;
print example::fact(4), "\n";
print example::my_mod(23,7), "\n";
print $example::My_variable + 4.5, "\n";
<ctrl-d>
24
2
7.5
unix >

Building a Python module

Finally, let's build a module for Python (shown for Irix).

unix > swig -python example.i
Generating wrappers for Python
unix > gcc -c -fpic example.c example_wrap.c -I/usr/local/include/python2.0
unix > gcc -shared example.o example_wrap.o -o examplemodule.so
unix > python
Python 2.0 (#6, Feb 21 2001, 13:29:45)
[GCC egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)] on linux2
Type "copyright", "credits" or "license" for more information.     
>>> import example
>>> example.fact(4)
24
>>> example.my_mod(23,7)
2
>>> example.cvar.My_variable + 4.5
7.5

Shortcuts

To the truly lazy programmer, one may wonder why we needed the extra interface file at all. As it turns out, you can often do without it. For example, you could also build a Perl5 module by just running SWIG on the C source and specifying a module name as follows

% swig -perl5 -module example example.c
unix > gcc -c example.c example_wrap.c \
	-I/usr/local/lib/perl5/sun4-solaris/5.003/CORE
unix> ld -G example.o example_wrap.o -o example.so
unix > perl5.003
use example;
print example::fact(4), "\n";
print example::my_mod(23,7), "\n";
print $example::My_variable + 4.5, "\n";
<ctrl-d>
24
2
7.5

Of course, there are some restrictions as SWIG is not a full C/C++ parser. If you make heavy use of the C preprocessor, complicated declarations, or C++, giving SWIG a raw source file probably isn't going to work very well (in this case, you would probably want to use a separate interface file).

SWIG provides its own version of the C preprocessor. Thus, if you want to make a combination SWIG/C header file, you might write the following:

/* File : example.h */
#ifdef SWIG
%module example
%include tclsh.i
#endif
extern double My_variable;
extern int    fact(int);
extern int    my_mod(int n, int m);

Building libraries and modules

In addition to generating wrapper code, SWIG provides extensive support for handling multiple files and building interface libraries. For example, our example.i file, could be used in another interface as follows :

%module foo
%include example.i             // Get definitions from example.i

... Now more declarations ...

In a large system, an interface might be built from a variety of pieces like this :

%module package

%include network.i
%include file.i
%include graphics.i
%include objects.i
%include simulation.i

SWIG comes with a library of existing functions known as the SWIG library. The library contains a mix of language independent and language dependent functionality. For example, the file `array.i' provides access to C arrays while the file `wish.i' includes specialized code for rebuilding the Tcl wish interpreter. Using the library, you can use existing modules to build up your own personalized environment for building interfaces. If changes are made to any of the components, they will appear automatically the next time SWIG is run.

C syntax, but not a C compiler

SWIG uses ANSI C syntax, but is not a full ANSI C compiler. By using C syntax, SWIG is relatively easy to use with most C programs. This avoids the problems with other interface generation tools that require programs to formally specify an interface in a special purpose interface definition language. On the other hand, using C syntax can be ambiguous. For example, if you have the following declaration,

int foo(double *a);

SWIG doesn't know if a is an array of some fixed size, a dynamically allocated block of memory, a single value, or an output value of the function. For the most part, SWIG takes a literal approach (a is obviously a double *) and leaves it up to the user to use the function in a correct manner. Fortunately, there are several ways to help SWIG out using additional directives and "helper" functions. Thus, the input to SWIG is often a mix of C declarations, special directives and hints. Like Perl, there is almost always more than one way to do almost anything.

SWIG does not currently parse every conceivable type of C declaration that it might encounter in a C/C++ file. Many things may be difficult or impossible to integrate with a scripting language. Thus, SWIG may not recognize certain advanced C/C++ constructs. Of course, SWIG's parser is always being improved so currently unsupported features may be supported in later releases.

Non-intrusive interface building

When used as intended, SWIG requires minimal modification to existing C code. This makes SWIG extremely easy to use with existing packages and promotes software reuse and modularity. By making the C code independent of the high level interface, you can change the interface and reuse the code in other applications. It is also possible to support different types of interfaces depending on the application.

Hands off code generation

SWIG is designed to produce working code that needs no hand-modification (in fact, if you look at the output, you probably won't want to modify it). Ideally, SWIG should be invoked automatically inside a Makefile just as one would call the C compiler. You should think of your scripting language interface being defined entirely by the input to SWIG, not the resulting output file. While this approach may limit flexibility for hard-core hackers, it allows others to forget about the low-level implementation details.


SWIG 1.3 - Last Modified : November 28, 2001