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.
From the standpoint of C/C++, a lot of people use SWIG because they want to break out of the traditional monolithic C programming model which usually results in programs that resemble this:
SWIG tries to make the problem of C/C++ integration as painless as possible. This allows you to focus on the underlying C program and using the high-level language interface, but not the tedious and complex chore of making the two languages talk to each other. At the same time, SWIG recognizes that all applications are different. Therefore, it provides a wide variety of customization features that let you change almost every aspect of the language bindings. This is the main reason why SWIG has such a large user manual ;-).
/* 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) :
/* 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.
unix > swig -tcl example.i 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.
unix > swig -perl5 example.i 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 >
unix > swig -python example.i unix > gcc -c -fpic example.c example_wrap.c -I/usr/local/include/python2.0 unix > gcc -shared example.o example_wrap.o -o _example.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
unix > swig -perl5 -module example example.h 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
It is important to stress that SWIG is not a simplistic C++ lexing tool like several apparently similar wrapper generation tools. SWIG not only parses C++, it implements the full C++ type system and it is able to understand C++ semantics. SWIG generates its wrappers with full knowledge of this information. As a result, you will find SWIG to be just as capable of dealing with nasty corner cases as it is in wrapping simple C++ code. In fact, SWIG is able handle C++ code that stresses the very limits of many C++ compilers.
SWIG is a command line tool and as such can be incorporated into any build system that supports invoking external tools/compilers. SWIG is most commonly invoked from within a Makefile, but is also known to be invoked from from popular IDEs such as Microsoft Visual Studio.
If you are using the GNU Autotools (Autoconf/ Automake/ Libtool) to configure SWIG use in your project, the SWIG Autoconf macros can be used. The primary macro is ac_pkg_swig, see http://www.gnu.org/software/ac-archive/htmldoc/ac_pkg_swig.html. The ac_python_devel macro is also helpful for generating Python extensions. See the Autoconf Macro Archive for further information on this and other Autoconf macros.
There is growing support for SWIG in some build tools, for example CMake is a cross-platform, open-source build manager with built in support for SWIG. CMake can detect the SWIG executable and many of the target language libraries for linking against. CMake knows how to build shared libraries and loadable modules on many different operating systems. This allows easy cross platform SWIG development. It also can generate the custom commands necessary for driving SWIG from IDE's and makefiles. All of this can be done from a single cross platform input file. The following example is a CMake input file for creating a python wrapper for the SWIG interface file, example.i:
The above example will generate native build files such as makefiles, nmake files and Visual Studio projects which will invoke SWIG and compile the generated C++ files into _example.so (UNIX) or _example.dll (Windows).# This is a CMake example for Python FIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE}) FIND_PACKAGE(PythonLibs) INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) SET(CMAKE_SWIG_FLAGS "") SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES CPLUSPLUS ON) SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES SWIG_FLAGS "-includeall") SWIG_ADD_MODULE(example python example.i example.cxx) SWIG_LINK_LIBRARIES(example ${PYTHON_LIBRARIES})
Ironically, the freedom that SWIG provides is countered by an extremely conservative approach to code generation. At it's core, SWIG tries to distill even the most advanced C++ code down to a small well-defined set of interface building techniques based on ANSI C programming. Because of this, you will find that SWIG interfaces can be easily compiled by virtually every C/C++ compiler and that they can be used on any platform. Again, this is an important part of staying out of the programmer's way----the last thing any developer wants to do is to spend their time debugging the output of a tool that relies on non-portable or unreliable programming features.