4 SWIG and C++

This chapter describes SWIG's support for wrapping C++. As a prerequisite, you should first read the chapter SWIG Basics to see how SWIG wraps ANSI C. Support for C++ is mostly an extension of ANSI C wrapping and that material will be useful in understanding this chapter.

Comments on C++ Wrapping

Because of its sheer complexity, and the fact that C++ can be difficult to integrate with itself let alone other languages, SWIG is only able to provide support for a subset of C++ features.

In part, the problem with C++ wrapping is that there is no semantically obvious (or automatic ) way to map many of its advanced features into other languages. As a simple example, consider the problem of wrapping C++ multiple inheritance to a target language with no such support. Similarly, the use of overloaded operators and overloaded functions can be problematic when no such capability exists in a target language.

A more subtle issue with C++ has to do with the way that some C++ programmers think about programming libraries. In the world of SWIG, what you are really trying to do is to create binary-level software components for use in other languages. In order for this to work, a "component" has to contain real executable instructions and there has to be some kind of binary linking mechanism for accessing its functionality. In contrast, C++ has increasingly relied upon generic programming and templates for much of its functionality. Although templates are a powerful feature, they are largely orthogonal to the whole notion of binary components and libraries. For example, an STL vector does not define any kind of binary object for which SWIG can just create a wrapper. To further complicate matters, these libraries often utilize a lot of behind the scenes magic in which the semantics of seemingly basic operations (e.g., pointer dereferencing, procedure call, etc.) can be changed in dramatic and sometimes non-obvious ways. Although this "magic" may present few problems in a C++-only universe, it greatly complicates the problem of crossing language boundaries and provides many opportunities to shoot yourself in the foot. You will have to be careful.

To wrap C++, SWIG takes a deliberately conservative, low-level, and non-intrusive approach. For one, SWIG generates all of its C++ wrappers so that they have standard ANSI C linkage. This low-level interface is then used as a basis for building the resulting scripting language module (which may or may not utilize OO features). Second, SWIG does not encapsulate C++ classes inside special adaptor or proxy classes, it does not rely upon additional template magic, nor does it use C++ inheritance. The last thing that most C++ programs need is even more compiler magic. Therefore, SWIG tries to maintain a very strict and clean separation between the implementation of your C++ application and the resulting wrapper code. You might say that SWIG has been written to follow the principle of least surprise--it does not play sneaky tricks with the C++ type system, it doesn't mess with your class hierarchies, and it doesn't introduce new semantics. Although this approach might not provide the most seamless integration with C++, it is safe, simple, portable, and debuggable.

Supported C++ features

SWIG currently supports the following C++ features :

The following C++ features are not currently supported :

SWIG's C++ support is always improving so some of these limitations may be lifted in future releases. However, we make no promises.

A simple C++ example

The following code shows a SWIG interface file for a simple C++ class.

%module list
%{
#include "list.h"
%}

// Very simple C++ example for linked list

class List {
public:
  List();
  ~List();
  int  search(char *value);
  void insert(char *);
  void remove(char *);
  char *get(int n);
  int  length;
static void print(List *l);
};

When compiling C++ code, it is critical that SWIG be called with the `-c++' option. This changes the way a number of critical features such as memory management are handled. It also enables the recognition of C++ keywords. Without the -c++ flag, SWIG will either issue a warning or a large number of syntax errors if it encounters C++ code in an interface file.

Constructors and destructors

C++ constructors and destructors are translated into accessor functions such as the following :

List * new_List(void) {
	return new List;
}
void delete_List(List *l) {
	delete l;
}

If a C++ class does not define any public constructors or destructors, SWIG will automatically create a default constructor or destructor. However, there are a few rules that define this behavior: SWIG should never generate a constructor or destructor for a class in which it is illegal to do so. However, if it is necessary to disable the default constructor/destructor creation, the %nodefault directive can be used:
%nodefault;   // Disable creation of constructor/destructor
class Foo {
...
};
%makedefault;
Compatibility Note: The generation of default constructors/destructors was made the default behavior in SWIG 1.3.7. This may break certain older modules, but the old behavior can be easily restored using %nodefault or the -nodefault command line option. Furthermore, in order for SWIG to properly generate (or not generate) default constructors, it must be able to gather information from both the private and protected sections (specifically, it needs to know if a private or protected constructor/destructor is defined). In older versions of SWIG, it was fairly common to simply remove or comment out the private and protected sections of a class due to parsing limitations. However, this removal may now cause SWIG to erroneously generate constructors for classes that define a constructor in those sections. Consider restoring those sections in the interface or using %nodefault to fix the problem.

Member functions

All member functions are roughly translated into accessor functions like this :

int List_search(List *obj, char *value) {
	return obj->search(value);
}

This translation is the same even if the member function has been declared as virtual.

It should be noted that SWIG does not actually create a C accessor function in the code it generates. Instead, member access such as obj->search(value) is directly inlined into the generated wrapper functions. However, the name and calling convention of the wrappers match the accessor function prototype described above.

Static members

Static member functions are called directly without making any special transformations. For example, the static member function print(List *l) directly invokes List::print(List *l) in the generated wrapper code.

Usually, static members are accessed as functions with names in which the class name has been prepended with an underscore. For example, List_print.

Member data

Member data is handled in exactly the same manner as for C structures. A pair of accessor functions will be created. For example :

int List_length_get(List *obj) {
	return obj->length;
}
int List_length_set(List *obj, int value) {
	obj->length = value;
	return value;
}

A read-only member can be created using the %readonly and %readwrite directives. For example, we probably wouldn't want the user to change the length of a list so we could do the following to make the value available, but read-only.

class List {
public:
...
%readonly
	int length;
%readwrite
...
};
Similarly, all data attributes declared as const are wrapped as read-only members.

Protection

SWIG can only wrap class members that are declared public. Anything specified in a private or protected section will simply be ignored (although the internal code generator sometimes looks at the contents of the private and protected sections so that it can properly generate code for default constructors and destructors).

By default, members of a class definition are assumed to be private until you explicitly give a `public:' declaration (This is the same convention used by C++).

Enums and constants

Enumerations and constants placed in a class definition are mapped into constants with the classname as a prefix. For example :

class Swig {
public:
	enum {ALE, LAGER, PORTER, STOUT};
};

Generates the following set of constants in the target scripting language :

Swig_ALE = Swig::ALE
Swig_LAGER = Swig::LAGER
Swig_PORTER = Swig::PORTER
Swig_STOUT = Swig::STOUT

Members declared as const are wrapped as read-only members and do not create constants.

References and pointers

C++ references are supported, but SWIG transforms them back into pointers. For example, a declaration like this :

class Foo {
public:
	double bar(double &a);
}

is accessed using a function similar to this:

double Foo_bar(Foo *obj, double *a) {
	obj->bar(*a);
}
Functions that return a reference are remapped to return a pointer instead. For example:
class Bar {
public:
     double &spam();
};
Generates code like this:
double *Bar_spam(Bar *obj) {
   double &result = obj->spam();
   return &result;
}
Don't return references to objects allocated as local variables on the stack. SWIG doesn't make a copy of the objects so this will probably cause your program to crash.

Pass and return by value

Occasionally, a C++ program will pass and return class objects by value. For example, a function like this might appear:
Vector cross_product(Vector a, Vector b);
If no information is supplied about Vector, SWIG creates a wrapper function similar to the following:
Vector *wrap_cross_product(Vector *a, Vector *b) {
   Vector x = *a;
   Vector y = *b;
   Vector r = cross_product(x,y);
   return new Vector(r);
}
In order for the wrapper code to compile, Vector must define a copy constructor and have a default constructor.

If Vector is defined as class in the interface, SWIG changes the wrapper code by encapsulating the arguments inside a special C++ template wrapper class. This produces a wrapper that looks like this:

Vector cross_product(Vector *a, Vector *b) {
   SwigValueWrapper<Vector> x = *a;
   SwigValueWrapper<Vector> y = *b;
   SwigValueWrapper<Vector> r = cross_product(x,y);
   return new Vector(r);
}
This transformation is a little sneaky, but it provides support for pass-by-value even when a class does not provide a default constructor and it makes it possible to properly support a number of SWIG's customization options. The definition of SwigValueWrapper can be found by reading the SWIG wrapper code. This class is really nothing more than a thin wrapper around a pointer.

Note: this transformation has no effect on typemaps or any other part of SWIG---it should be transparent except that you will see this code when reading the SWIG output file.

Note: This template transformation is new in SWIG-1.3.11 and may be refined in future SWIG releases. In practice, it is only necessary to do this for classes that don't define a default constructor. However, SWIG sometimes applies the transformation when it's not needed (this would occur if a declaration involving a value was wrapped before SWIG was able to determine if a class had a default constructor or not).

Note: The use of this template only occurs when objects are passed or returned by value. It is not used for C++ pointers or references.

Note: The performance of pass-by-value is especially bad for large objects and should be avoided if possible (consider using references instead).

Inheritance

SWIG supports C++ public inheritance of classes and allows both single and multiple inheritance. The SWIG type-checker knows about the relationship between base and derived classes and allows pointers to any object of a derived class to be used in functions of a base class. The type-checker properly casts pointer values and is safe to use with multiple inheritance.

SWIG does not support private or protected inheritance (it is parsed, but it has no effect on the generated code). Note: private and protected inheritance do not define an "isa" relationship between classes so it would have no effect on type-checking anyways.

The following example shows how SWIG handles inheritance. For clarity, the full C++ code has been omitted.

// shapes.i
%module shapes
%{
#include "shapes.h"
%}

class Shape {
public:
        double x,y;
	virtual double area() = 0;
	virtual double perimeter() = 0;
	void    set_location(double x, double y);
};
class Circle : public Shape {
public:
	Circle(double radius);
	~Circle();
	double area();
	double perimeter();
};
class Square : public Shape {
public:
	Square(double size);
	~Square();
	double area();
	double perimeter();
}

When wrapped into Python, we can now perform the following operations :

$ python
>>> import shapes
>>> circle = shapes.new_Circle(7)
>>> square = shapes.new_Square(10)
>>> print shapes.Circle_area(circle)
153.93804004599999757
>>> print shapes.Shape_area(circle)
153.93804004599999757
>>> print shapes.Shape_area(square)
100.00000000000000000
>>> shapes.Shape_set_location(square,2,-3)
>>> print shapes.Shape_perimeter(square)
40.00000000000000000
>>>
In this example, Circle and Square objects have been created. Member functions can be invoked on each object by making calls to Circle_area, Square_area, and so on. However, the same results can be accomplished by simply using the Shape_area function on either object.

One important point concerning inheritance is that the low-level accessor functions are only generated for classes in which they are actually declared. For instance, in the above example, the method set_location() is only accessible as Shape_set_location() and not as Circle_set_location() or Square_set_location(). Of course, the Shape_set_location() function will accept any kind of object derived from Shape. Similarly, accessor functions for the attributes x and y are generated as Shape_x_get(), Shape_x_set(), Shape_y_get(), and Shape_y_set(). Functions such as Circle_x_get() are not available--instead you should use Shape_x_get().

Although the low-level C-like interface is functional, most language modules also produce a higher level OO interface using a technique known as shadow classing. This approach is described shortly and can be used to provide a more natural C++ interface.

Compatibility Note: Starting in version 1.3.7, SWIG only generates low-level accessor wrappers for the declarations that are actually defined in each class. This differs from SWIG1.1 which used to inherit all of the declarations defined in base classes and regenerate specialized accessor functions such as Circle_x_get(), Square_x_get(), Circle_set_location(), and Square_set_location(). This old behavior results in huge amounts of replicated code for large class hierarchies and makes it awkward to build applications spread across multiple modules (since accessor functions are duplicated in every single module). It is also unnecessary to have such wrappers when advanced features like shadow-classing are used. Future versions of SWIG may apply further optimizations such as not regenerating wrapper functions for virtual members that are already defined in a base class.

Renaming

C++ member functions and data can be renamed with the %name directive. The %name directive only replaces the member function name. For example :

class List {
public:
  List();
%name(ListSize) List(int maxsize);
  ~List();
  int  search(char *value); 
%name(find)    void insert(char *); 
%name(delete)  void remove(char *); 
  char *get(int n);
  int  length;
static void print(List *l);
};

This will create the functions List_find, List_delete, and a function named new_ListSize for the overloaded constructor.

The %name directive can be applied to all members including constructors, destructors, static functions, data members, and enumeration values.

The class name prefix can also be changed by specifying

%name(newname) class List {
...
}
Although the %name() directive can be used to help deal with overloaded methods, it really doesn't work very well because it requires a lot of additional markup in your interface. Keep reading for a better solution.

Wrapping Overloaded Functions and Methods

This section describes the problem of wrapping overloaded C++ functions and methods. This has long been a limitation of SWIG that has only recently been addressed (primarily because we couldn't quite figure out how to do it without causing a head-explosion or serious reliability problems). However, in order to understand the reasoning behind the current solution, it is important to better understand the problem.

In C++, functions and methods can be overloaded by declaring them with different type signatures. For example:

void foo(int);
void foo(double);
void foo(Bar *b, Spam *s, int );
Later, when a call to function foo() is made, the determination of which function to invoke is made by looking at the types of the arguments. For example:
int x;
double y;
Bar *b;
Spam *s;
int z;
...
foo(x);        // Calls foo(int)
foo(y);        // Calls foo(double)
foo(b,s,z);    // Calls foo(Bar *, Spam *, int)
It is important to note that the selection of the overloaded method or function is made by the C++ compiler and occurs at compile time. It does not occur as your program runs.

Internal to the C++ compiler, overloaded functions are mapped to unique identifiers using a name-mangling technique where the arguments are used to create a unique type signature that is appended to the name. This produces three unique function names that might look like this:

void foo__Fi(int);
void foo__Fd(double);
void foo__FP3BarP4Spami(Bar *, Spam *, int);
Calls to foo() are then mapped to an appropriate version depending on the types of arguments passed.

The implementation of overloaded methods in C++ is difficult to translate directly to a scripting language environment because it relies on static type-checking and compile-time binding of methods--neither of which map to the dynamic environment of an interpreter. For example, in Python, Perl, and Tcl, it is simply impossible to define three entirely different versions of a function with exactly the same name within the same scope. The repeated definitions simply replace previous definitions.

Therefore, to solve the overloading problem, let's first look at several approaches that have been proposed as solutions, but which are NOT used to solve the overloading problem in SWIG.

Alas, what to do about overloading?

Although it would be nice to support an advanced wrapping technique such as dynamic dispatch or trial execution, both of these techniques are difficult (if not impossible) to implement in a completely general manner that would work in all situations and with all combinations of SWIG customization features. Therefore, rather than generate wrappers that only work some of the time, SWIG takes a slightly different approach.

Starting with SWIG-1.3.7, a very simple enhancement has been added to the %rename directive to help disambiguate overloaded functions and methods. Normally, the %rename directive is used to rename a declaration everywhere in an interface file. For example, if you write this,

%rename(foo) bar;
all occurences of "bar" will be renamed to "foo" (this feature was described a little earlier in this chapter in the section "Renaming Declarations"). By itself, this doesn't do anything to help fix overloaded methods. However, the %rename directive can now be parameterized as shown in this example:
/* Forward renaming declarations */
%rename(foo_i) foo(int); 
%rename(foo_d) foo(double);
...
void foo(int);           // Becomes 'foo_i'
void foo(char *c);       // Stays 'foo' (not renamed)

class Spam {
public:
   void foo(int);      // Becomes 'foo_i'
   void foo(double);   // Becomes 'foo_d'
   ...
};
Since, the %rename declaration is used to declare a renaming in advance, it can be placed at the start of an interface file. This makes it possible to apply a consistent name resolution without having to modify header files. For example:
%module foo

/* Rename these overloaded functions */
%rename(foo_i) foo(int); 
%rename(foo_d) foo(double);

%include "header.h"
When used in this simple form, the renaming is applied to all global functions and member functions that match the prototype. If you only want the renaming to apply to a certain scope, the C++ scope resolution operator (::) can be used. For example:
%rename(foo_i) ::foo(int);      // Only rename foo(int) in the global scope.
                                // (will not rename class members)

%rename(foo_i) Spam::foo(int);  // Only rename foo(int) in class Spam
When a renaming operator is applied to a class as in Spam::foo(int), it is applied to that class and all derived classes. This can be used to apply a consistent renaming across an entire class hierarchy with only a few declarations. For example:
%rename(foo_i) Spam::foo(int);
%rename(foo_d) Spam::foo(double);

class Spam {
public:
   virtual void foo(int);      // Renamed to foo_i
   virtual void foo(double);   // Renamed to foo_d
   ...
};

class Bar : public Spam {
public:
   virtual void foo(int);      // Renamed to foo_i
   virtual void foo(double);   // Renamed to foo_d
...
};

class Grok : public Bar {
public:
   virtual void foo(int);      // Renamed to foo_i
   virtual void foo(double);   // Renamed to foo_d
...
};
Depending on your application, it may make more sense to include %rename specifications in the class definition. For example:
class Spam {
%rename(foo_i) foo(int);
%rename(foo_d) foo(double);
public:
   virtual void foo(int);      // Renamed to foo_i
   virtual void foo(double);   // Renamed to foo_d
   ...
};

class Bar : public Spam {
public:
   virtual void foo(int);      // Renamed to foo_i
   virtual void foo(double);   // Renamed to foo_d
...
};
In this case, the %rename directives still get applied across the entire inheritance hierarchy, but it's no longer necessary to explicitly specify the class prefix Spam::.

A special form of %rename can be used to apply a renaming just to class members (of all classes):

%rename(foo_i) *::foo(int);   // Only rename foo(int) if it appears in a class.
Note: the *:: syntax is non-standard C++, but the '*' is meant to be a wildcard that matches any class name (we couldn't think of a better alternative so if you have a better idea, send email to swig-dev@cs.uchicago.edu).

Although the %rename approach does not automatically solve the overloading problem for you (you have to supply a name), SWIG's error messages have been improved to help. For example, consider this interface file:

%module foo

class Spam {
public:
   void foo(int);
   void foo(double);
   void foo(Bar *, Spam *, int);
};
If you run SWIG on this file, you will get the following error messages:
foo.i:6. Overloaded declaration ignored.  Spam::foo(double )
foo.i:5. Previous declaration is Spam::foo(int )
foo.i:7. Overloaded declaration ignored.  Spam::foo(Bar *,Spam *,int )
foo.i:5. Previous declaration is Spam::foo(int )
The error messages indicate the problematic functions along with their type signature. In addition, the previous definition is supplied. Therefore, you can just look at these errors and decide how you want to handle the overloaded functions. For example:
%module foo
%rename(foo_d)         Spam::foo(double);               // name foo_d
%rename(foo_barspam)   Spam::foo(Bar *, Spam *, int);   // name foo_barspam
...
class Spam { 
...
};
And again, for a class hierarchy, you may be able to solve all of the problems by just renaming members in the base class--those renamings automatically propagate to all derived classes.

Another way to resolve overloaded methods is to simply eliminate conflicting definitions. An easy way to do this is to use the %ignore directive. %ignore works exactly like %rename except that it forces a declaration to disappear. For example:

%ignore foo(double);          // Ignore all foo(double)
%ignore Spam::foo;            // Ignore foo in class Spam
%ignore Spam::foo(double);    // Ignore foo(double) in class Spam
%ignore *::foo(double);       // Ignore foo(double) in all classes
When applied to a base class, %ignore forces all definitions in derived clases to disappear. For example, %ignore Spam::foo(double) will eliminate foo(double) in Spam and all classes derived from Spam.

A few implementation notes about the enhanced %rename directive and %ignore:

Wrapping overloaded operators

Starting in SWIG-1.3.10, C++ overloaded operator declarations can be wrapped. For example, consider a class like this:
class Complex {
private:
  double rpart, ipart;
public:
  Complex(double r = 0, double i = 0) : rpart(r), ipart(i) { }
  Complex(const Complex &c) : rpart(c.rpart), ipart(c.ipart) { }
  Complex &operator=(const Complex &c) {
    rpart = c.rpart;
    ipart = c.ipart;
    return *this;
  }
  Complex operator+(const Complex &c) const {
    return Complex(rpart+c.rpart, ipart+c.ipart);
  }
  Complex operator-(const Complex &c) const {
    return Complex(rpart-c.rpart, ipart-c.ipart);
  }
  Complex operator*(const Complex &c) const {
    return Complex(rpart*c.rpart - ipart*c.ipart,
		   rpart*c.ipart + c.rpart*ipart);
  }
  Complex operator-() const {
    return Complex(-rpart, -ipart);
  }
  double re() const { return rpart; }
  double im() const { return ipart; }
};
When operator declarations appear, they are handled in exactly the same manner as regular methods. However, the names of these methods are set to strings like "operator +" or "operator -". The problem with these names is that they are illegal identifiers in most scripting languages. For instance, you can't just create a method called "operator +" in Python--there won't be any way to call it.

Some language modules already know how to automatically handle certain operators (mapping them into operators in the target language). However, the underlying implementation of this is really managed in a very general way using the %rename directive. For example, in Python a declaration similar to this is used:

%rename(__add__) Complex::operator+;
This binds the + operator to a method called __add__ (which is conveniently the same name used to implement the Python + operator). Internally, the generated wrapper code for a wrapped operator will look something like this pseudocode:
_wrap_Complex___add__(args) {
   ... get args ...
   obj->operator+(args);
   ...
}
When used in the target language, it may now be possible to use the overloaded operator normally. For example:
>>> a = Complex(3,4)
>>> b = Complex(5,2)
>>> c = a + b           # Invokes __add__ method
It is important to realize that there is nothing magical happening here. The %rename directive really only picks a valid method name. If you wrote this:
%rename(add) operator+;
The resulting scripting interface might work like this:
a = Complex(3,4)
b = Complex(5,2)
c = a.add(b)      # Call a.operator+(b)
All of the techniques described to deal with overloaded functions also apply to operators. For example:
%ignore Complex::operator=;             // Ignore = in class Complex
%ignore *::operator=;                   // Ignore = in all classes
%ignore operator=;                      // Ignore = everywhere.

%rename(__sub__) Complex::operator-; 
%rename(__neg__) Complex::operator-();  // Unary - 
The last part of this example illustrates how multiple definitions of the operator- method might be handled.

Handling operators in this manner is mostly straightforward. However, there are a few subtle issues to keep in mind:

Adding new methods

New methods can be added to a class using the %addmethods directive. This directive is primarily used in conjunction with shadow classes to add additional functionality to an existing class. For example :

%module vector
%{
#include "vector.h"
%}

class Vector {
public:
	double x,y,z;
	Vector();
	~Vector();
	... bunch of C++ methods ...
	%addmethods {
		char *__str__() {
			static char temp[256];
			sprintf(temp,"[ %g, %g, %g ]", v->x,v->y,v->z);
			return &temp[0];
		}
	}
};

This code adds a __str__ method to our class for producing a string representation of the object. In Python, such a method would allow us to print the value of an object using the print command.

>>>
>>> v = Vector();
>>> v.x = 3
>>> v.y = 4
>>> v.z = 0
>>> print(v)
[ 3.0, 4.0, 0.0 ]
>>>

The %addmethods directive follows all of the same conventions as its use with C structures.

Templates

In all versions of SWIG, template type names may appear anywhere a type is expected in an interface file. For example:
void foo(vector<int> *a, int n);
Starting with SWIG-1.3.7, simple C++ template declarations can also be wrapped. Before discussing this any further, there are a few things you need to know about template wrapping. First, a bare C++ template does not define any sort of runnable object-code for which SWIG can normally create a wrapper. Therefore, in order to wrap a template, you need to give SWIG information about a particular template instantiation (e.g., vector<int>, array<double>, etc.). Second, an instantiation name such as vector<int> is generally not a valid identifier name in most target languages. Thus, you will need to give the template instantiation a more suitable name such as intvector when creating a wrapper.

To illustrate, consider the following (and admittedly lame) template class declaration:

// File : list.h
template<class T> class List {
private:
    T *data;
    int nitems;
    int maxitems;
public:
    List(int max) {
      data = new T [max];
      nitems = 0;
      maxitems = max;
    }
    ~List() {
      delete [] data;
    };
    void append(T obj) {
      if (nitems < maxitems) {
        data[nitems++] = obj;
      }
    }
    int length() {
      return nitems;
    }
    T get(int n) {
      return data[n];
    }
};
By itself, this template declaration is useless--SWIG simply ignores it because it doesn't know how to generate any code until unless a definition of T is provided.

To create wrappers for a specific template instantiation, use the %template directive like this:

/* Instantiate a few different versions of the template */
%template(intList) List<int>;
%template(doubleList) List<double>;
The argument to %template() is the name of the instantiation in the target language. Most target languages do not recognize identifiers such as List<int>. Therefore, each instantiation of a template has to be associated with a nicely formatted identifier such as intList or doubleList. Furthermore, due to the details of the underlying implementation, the name you select has to be unused in both C++ and the target scripting language (e.g., the name must not match any existing C++ typename, class name, or declaration name).

Since most C++ compilers are nothing more than glorified preprocessors (sic) and C++ purists really hate macros, SWIG internally handles templates by converting them into macros and performing expansions using the preprocessor (well, actually it's somewhat more complicated than this, but the preprocessor is used for part of it). Specifically, the %template(intList) List<int> declaration results in a macro expansion that generates code roughly like this (which is then parsed to create the interface):

// Example of how templates are internally expanded by SWIG
%{
// Define a nice name for the instantiation
typedef List<int> intList;
%}
// Provide a simple class definition with types filled in
class intList {
private:
    int *data;
    int nitems;
    int maxitems;
public:
    intList(int max) {
      data = new int [max];
      nitems = 0;
      maxitems = max;
    }
    ~intList() {
      delete [] data;
    };
    void append(int obj) {
      if (nitems < maxitems) {
        data[nitems++] = obj;
      }
    }
    int length() {
      return nitems;
    }
    int get(int n) {
      return data[n];
    }
};
SWIG can also generate wrappers for function templates using a similar technique. For example:
// Function template
template T max(T a, T b) { return a > b ? a : b; }

// Make some different versions of this function
%template(maxint) max<int>;
%template(maxdouble) max<double>;
In this case, maxint and maxdouble become unique names for specific instantiations of the function.

When a template is instantiated using %template, information about that class is saved by SWIG and used elsewhere in the program. For example, if you wrote code like this,

...
%template(intList) List<int>;
...
class UltraList : public List<int> {
   ...
};
then SWIG knows that List<int> was already wrapped as a class called intList and arranges to handle the inheritance correctly. If, on the other hand, nothing is known about List<int>, you will get a warning message similar to this:
example.h:42. Nothing known about class 'List<int >' (ignored). 
example.h:42. Maybe you forgot to instantiate 'List<int >' using %template. 

If a template class inherits from another template class, you need to make sure that base classes are instantiated before derived classes. For example:

template<class T> class Foo {
...
};

template<class T> class Bar : public Foo<T> {
...
};

// Instantiate base classes first 
%template(intFoo) Foo<int>;
%template(doubleFoo) Foo<double>;

// Now instantiate derived classes
%template(intBar) Bar<int>;
%template(doubleBar) Bar<double>;
The order is important since SWIG uses the instantiation names to properly set up the inheritance hierarchy in the resulting wrapper code (and base classes need to be wrapped before derived classes). Don't worry--if you get the order wrong, SWIG will generate an warning message.

If you have to instantiate a lot of different classes for many different types, you might consider writing a SWIG macro. For example:

%define TEMPLATE_WRAP(T,prefix) 
%template(prefix ## Foo) Foo<T>;
%template(prefix ## Bar) Bar<T>;
...
%enddef

TEMPLATE_WRAP(int, int)
TEMPLATE_WRAP(double, double)
TEMPLATE_WRAP(char *, String)
...

If your goal is to make someone's head explode more than usual, SWIG directives such as %rename and %addmethods can be included directly in template definitions. Not only that, since SWIG has the advantage of using the preprocessor for template expansion, standard C preprocessor operators such as # and ## can be applied to template parameters (an obvious oversight of the C++ standard that SWIG now corrects). For example:

// File : list.h
template<class T> class List {
   ...
public:
    %rename(__getitem__) get(int);
    List(int max);
    ~List();
    ...
    T get(int index);
    %addmethods {
        char *__str__() {
            /* Make a string representation */
            ...
        }
        /* Return actual type of template instantiation as a string */
        char *ttype() {
            return #T;
        }
    }
};
In this example, the extra SWIG directives are propagated to every template instantiation.

In addition, the %addmethods directive can be used to add additional methods to a specific instantiation. For example:

%template(intList) List<int>;

%addmethods intList {
    void blah() {
          printf("Hey, I'm an intList!\n");
    }
};
Needless to say, SWIG's template support provides plenty of opportunities to break the universe. That said, an important final point is that SWIG performs no extensive error checking of templates! Specifically, SWIG does not perform type checking nor does it check to see if the actual contents of the template declaration make any sense. Since the C++ compiler will hopefully check this when it compiles the resulting wrapper file, there is no practical reason for SWIG to duplicate this functionality (besides, none of the SWIG developers are masochistic enough to want to implement this right now).

Finally, there are a few limitations in SWIG's current support for templates:

Pointers to Members

Starting with SWIG1.3.7, there is limited parsing support for pointers to C++ class members. For example:
double do_op(Object *o, double (Object::*callback)(double,double));
extern double (Object::*fooptr)(double,double);
%constant double (Object::*FOO)(double,double) = &Object::foo;
Although these kinds of pointers can be parsed and represented by the SWIG type system, few language modules know how to handle them due to implementation differences from standard C pointers. Readers are strongly advised to consult an advanced text such as the "The Annotated C++ Manual" for specific details.

When pointers to members are supported, the pointer value might appear as a special string like this:

>>> print example.FOO
_ff0d54a800000000_m_Object__f_double_double__double
>>>
In this case, the hexadecimal digits represent the entire value of the pointer which is usually the contents of a small C++ structure on most machines.

SWIG's type-checking mechanism is also more limited when working with member pointers. Normally SWIG tries to keep track of inheritance when checking types. However, no such support is currently provided for member pointers.

Partial class definitions

Since SWIG is still limited in its support of C++, it may be necessary to use partial class information in an interface file. However, since SWIG does not need the entire class specification to work, conditional compilation can be used to comment out problematic parts. For example, if you had a nested class definition, you might do this:
class Foo {
public:
#ifndef SWIG
   class Bar {
   public:
     ...
   };
#endif
   Foo();
  ~Foo();
   ...
};

Also, as a rule of thumb, SWIG should not be used on raw C++ source files.

A brief rant about const-correctness

A common issue when working with C++ programs is dealing with all possible ways in which the const qualifier (or lack thereof) will break your program, all programs linked against your program, and all programs linked against those programs. In fact, many C++ books actively encourage using const whenever possible (perhaps in an effort to maximize correctness through annoyance or by observing that an uncompilable program always runs correctly).

Although SWIG knows how to correctly deal with const in its internal type system and it knows how to generate wrappers that are free of const-related warnings, SWIG does not make any attempt to preserve const-correctness in the target language. Thus, it is possible to pass const qualified objects to non-const methods and functions. For example, consider the following code in C++:

const Object * foo();
void bar(Object *);

...
// C++ code
void blah() {
   bar(foo());         // Error: bar discards const
};
Now, consider the behavior when wrapped into a Python module:
>>> bar(foo())         # Okay
>>> 
Although this is clearly a violation of the C++ type-system, fixing the problem doesn't seem to be worth the added implementation complexity that would be required to support it in the SWIG run-time type system. There are no plans to change this in future releases (although we'll never rule anything out entirely).

The bottom line is that this particular issue does not appear to be a problem for most SWIG projects. Of course, you might want to consider using another tool if maintaining constness is the most important part of your project.

Where to go for more information


SWIG 1.3 - Last Modified : December 30, 2001