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, you are really trying 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 just have to be careful.
It is important to emphasize that SWIG takes a deliberately conservative and non-intrusive approach to C++ wrapping. SWIG does not encapsulate C++ classes inside special C++ adaptor or proxy classes, it does not rely upon templates, nor does it use C++ inheritance when generating wrappers. 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.
Most of this chapter focuses on the low-level procedural interface to C++ that is used as the foundation for all language modules. Keep in mind that most target languages also provide a high-level OO interface via proxy classes. A few general details about proxies can be found at the end of this chapter. However, more detailed coverage can be found in the documentation for each target language.
The following C++ features are not currently supported :
SWIG's C++ support is an ongoing project so some of these limitations may be lifted in future releases. However, we make no promises.
When wrapping 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.
When compiling and linking the resulting wrapper file, it is normal to use the C++ compiler. For example:
Unfortunately, the process varies slightly on each machine. Make sure you refer to the documentation on each target language for further details. The SWIG Wiki also has further details.$ swig -c++ -tcl example.i $ c++ -c example_wrap.cxx $ c++ example_wrap.o $(OBJS) -o example.so
%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);
};
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:
%nodefault; // Disable creation of constructor/destructor
class Foo {
...
};
%makedefault;
%nodefault can also take a class name. For example:
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 parser 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.%nodefault Foo; // Disable for class Foo only.
class List {
public:
List();
List(const List &); // Copy constructor
...
};
the copy constructor is mapped into an accessor function like this:
List *copy_List(List *f) {
return new List(*f);
}
Depending on the target language module, this function may be further
incorporated into object wrapping (wrapped a special method for object
copying for instance). However, if not, the above copy function will
be made available as an ordinary procedure.
Note: For a class X, SWIG only treats a constructor as a copy constructor if it can be applied to an object of type X or X *. If more than one copy constructor is defined, only the first definition that appears is used as the copy constructor--other definitions will result in a name-clash. Constructors such as X(const X &), X(X &), and X(X *) are handled as copy constructors in SWIG.
Note: SWIG does not generate a copy constructor wrapper unless one is explicitly declared in the class. This differs from the treatment of default constructors and destructors.
Compatibility note: Special support for copy constructors was not added until SWIG-1.3.12. In previous versions, copy constructors could be wrapped, but they had to be renamed. For example:
class Foo {
public:
Foo();
%name(CopyFoo) Foo(const Foo &);
...
};
For backwards compatibility, SWIG does not perform any special
copy-constructor handling if the constructor has been manually
renamed. For instance, in the above example, the name of the
constructor is set to new_CopyFoo(). This is the same as in
older versions.
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.
Usually, static members are accessed as functions with names in which the class name has been prepended with an underscore. For example, List_print.
class Foo {
public:
void bar(int x, int y = 3);
};
However, the implementation restricts the use of default arguments to values
that are public. The following example illustrates a very subtle semantic
incompatibility between SWIG and C++:
class Foo {
private:
int spam;
public:
void bar(int x, int y = spam); // Illegal in SWIG. Private default value
};
When this occurs, you will get a couple of warning messages like this:
This incompatibility arises because default values in C++ are evaluated in the same scope as the member function whereas SWIG evaluates them in the scope of a wrapper function (meaning that the values have to be public). The full set of arguments are needed in the wrappers in order to support a number of advanced customization features and the use of default arguments in ANSI C (which is not part of the ANSI standard).example.i:15. Warning 'spam' is private in this context. example.i:15. Warning. Can't set default argument (ignored)
There are several somewhat clumsy ways to work around this problem (which are not discussed here). However, a simpler solution may be to reconsider your design--is it really that critical to make the default argument private?
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 %immutable and
%mutable 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:
...
%immutable;
int length;
%mutable;
...
};
Alternatively, you can specify an immutable member in advance like this:
%immutable List::length;
...
class List {
...
int length; // Immutable by above directive
...
};
Similarly, all data attributes declared as const are wrapped as read-only members.
There are some subtle issues when wrapping data members that are themselves classes. For instance, if you had another class like this,
class Foo {
public:
List items;
...
then access to the items member actually uses pointers. For example:
List *Foo_items_get(Foo *self) {
return &self->items;
}
void Foo_items_set(Foo *self, List *value) {
self->items = *value;
}
More information about this can be found in the "Structure data
members" section of the SWIG Basics chapter.
Compatibility note: Read-only access used to be controlled by a pair of directives %readonly and %readwrite. Although these directives still work, they generate a warning message. Simply change the directives to %immutable; and %mutable; to silence the warning. Don't forget the extra semicolon!
Compatibility note: Prior to SWIG-1.3.12, all members of unknown type were wrapped into accessor functions using pointers. For example, if you had a structure like this
struct Foo {
size_t len;
};
and nothing was known about size_t, then accessors would be
written to work with size_t *. Starting in SWIG-1.3.12, this
behavior has been modified. Specifically, pointers will only
be used if SWIG knows that a datatype corresponds to a structure or
class. Therefore, the above code would be wrapped into accessors
involving size_t. This change is subtle, but it smooths over
a few problems related to structure wrapping and some of SWIG's
customization features.
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++).
A subtle access problem relates to default values of member functions. Specifically, default values must be public. Please go back to the section on default arguments for further details.
class Swig {
public:
enum {ALE, LAGER, PORTER, STOUT};
};
Generates the following set of constants in the target scripting language :
Members declared as const are wrapped as read-only members and do not create constants.Swig_ALE = Swig::ALE Swig_LAGER = Swig::LAGER Swig_PORTER = Swig::PORTER Swig_STOUT = Swig::STOUT
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);
}
As a special case, most language modules pass const references to primitive datatypes (int, short,
float, etc.) by value instead of pointers. For example, if you have a function like this,
it is called from a script as follows:void foo(const int &x);
Functions that return a reference are remapped to return a pointer instead. For example:foo(3) # Notice pass by value
class Bar {
public:
Foo &spam();
};
Generates code like this:
Foo *Bar_spam(Bar *obj) {
Foo &result = obj->spam();
return &result;
}
However, functions that return const references to primitive datatypes (int, short, etc.) normally
return the result as a value rather than a pointer. For example, a function like this,
will return integers such as 37 or 42 in the target scripting language rather than a pointer to an integer.const int &bar();
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.
Note: The special treatment for references to primitive datatypes is necessary to provide more seamless integration with more advanced C++ wrapping applications---especially related to templates and the STL. This was first added in SWIG-1.3.12.
If no information is supplied about Vector, SWIG creates a wrapper function similar to the following:Vector cross_product(Vector a, Vector b);
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 a
default constructor.
If Vector is defined as class in the interface, but it does not support a default constructor, 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 may 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.
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).
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 :
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.$ 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 >>>
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 proxy classes. This approach is described later and can be used to provide a more natural C++ interface.
Note: For the best results, SWIG requires all base classes to be defined in an interface. Otherwise, you may get an warning message like this:
If any base class is undefined, SWIG still generates correct type relationships. For instance, a function accepting a Foo * will accept any object derived from Foo regardless of whether or not SWIG actually wrapped the Foo class. If you really don't want to generate wrappers for the base class, but you want to silence the warning, you might consider using the %import directive to include the file that defines Foo. %import simply gathers type information, but doesn't generate wrappers. Alternatively, you could just define Foo as an empty class in the SWIG interface.example:18. Nothing known about class 'Foo'. Ignored.
Note: typedef-names can be used as base classes. For example:
class Foo {
...
};
typedef Foo FooObj;
class Bar : public FooObj { // Ok. Base class is Foo
...
};
Similarly, typedef allows unnamed structures to be used as base classes. For example:
typedef struct {
...
} Foo;
class Bar : public Foo { // Ok.
...
};
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 behavior resulted in huge amounts of replicated code for large class hierarchies and made 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 proxy classes 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.
A somewhat common question is whether or not the type-tag could be safely removed from the pointer. For instance, to get better performance, could you strip all type tags and just use simple integers instead?_808fea88_p_Circle
In general, the answer to this question is no. In the wrappers, all pointers are converted into a common data representation in the target language. Typically this is the equivalent of casting a pointer to void *. This means that any C++ type information associated with the pointer is lost in the conversion.
The problem with losing type information is that it is needed to properly support many advanced C++ features--especially multiple inheritance. For example, suppose you had code like this:
class A {
public:
int x;
};
class B {
public:
int y;
};
class C : public A, public B {
};
int A_function(A *a) {
return a->x;
}
int B_function(B *b) {
return b->y;
}
Now, consider the following code that uses void *.
In this code, both A_function() and B_function() may legally accept an object of type C * (via inheritance). However, one of the functions will always return the wrong result when used as shown. The reason for this is that even though p points to an object of type C, the casting operation doesn't work like you would expect. Internally, this has to do with the data representation of C. With multiple inheritance, the data from each base class is stacked together. For example:C *c = new C(); void *p = (void *) c; ... int x = A_function((A *) p); int y = B_function((B *) p);
------------ <--- (C *), (A *)
| A |
|------------| <--- (B *)
| B |
------------
Because of this stacking, a pointer of type C * may change
value when it is converted to a A * or B *.
However, this adjustment does not occur if you are converting from a
void *.
The use of type tags marks all pointers with the real type of the underlying object. This extra information is then used by SWIG generated wrappers to correctly cast pointer values under inheritance (avoiding the above problem).
One might be inclined to fix this problem using some variation of dynamic_cast<>. The only problem is that it doesn't work with void pointers, it requires RTTI support, and it only works with polymorphic classes (i.e., classes that define one or more virtual functions).
The bottom line: learn to live with type-tagged pointers.
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.
In C++, functions and methods can be overloaded by declaring them with different type signatures. For example:
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:void foo(int); void foo(double); void foo(Bar *b, Spam *s, 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.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)
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:
Calls to foo() are then mapped to an appropriate version depending on the types of arguments passed.void foo__Fi(int); void foo__Fd(double); void foo__FP3BarP4Spami(Bar *, Spam *, int);
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.
Although this certainly works, it is extremely annoying to explicitly annotate every class with a bunch of %name directives like that. It fact, it's so annoying that this really isn't a viable solution at all (except in cases where there is very little overloading). Dave sincerely apologizes for ever thinking that this approach was good enough--however, let's try to forget the past and move on.void foo(int); %name(foo_d) foo(double); %name(foo_barspam) foo(Bar *, Spam *, int);
Needless to say, this approach is not used by SWIG nor has it ever been seriously considered.foo__FP3BarP4Spami(b,s,i);
Although a lot more readable than the fully mangled version, this now has the problem of naming clashes. For instance, what is supposed to happen with these two functions?void foo(int); // becomes foo_i(int) void foo(double); // becomes foo_d(int) void foo(Bar *, Spam *, int); // becomes foo_BSi(int)
Also, what happens if the mangled version happens to match a legitimate identifier name used elsewhere in the program? One could use the %name directive to resolve such a conflict, but this tends to defeat the whole point. Although this might work in simple cases, there are still a number of obvious problems.void foo(int i); // ????? void foo(instance *obj); // ?????
Unfortunately, the numbering doesn't give any clues about what the actual function is. Also, if the order changes or a new function is added, all of the numbers might change--breaking all of the programs written against the interface. There is also a tiny problem of naming methods with multiple inheritance:void foo(int); // becomes foo_1(int) void foo(double); // becomes foo_2(int) void foo(Bar *, Spam *, int); // becomes foo_3(int)
class X {
public:
virtual void foo(int); // X_foo_1
virtual void foo(double); // X_foo_2
};
class Y {
public:
virtual void foo(long); // Y_foo_1
virtual void foo(Bar *, Spam *, int); // Y_foo_2
};
class Z : public X, public Y {
public:
virtual void foo(double); // Z_foo_1 ??? Mismatch X_foo_2
virtual void foo(Bar *, Spam *, int); // Z_foo_2 ???
// What happens to X_foo_1 and Y_foo_1 here?
};
In this case, the member functions have different names in the base class than they
do in a derived class! Clearly this is just bizarre and not particularly
obvious to someone who has to maintain the resulting code.
Again, this doesn't seem to be a viable solution except in very simple cases.
wrap_foo(args):
if len(args) == 3:
if (args[0].type == Bar and
args[1].type == Spam and
args[2].type == int):
foo((Bar *) arg[0], (Spam *) arg[1], (int) arg[2])
else if len(args) == 1:
if args[0].type == int:
foo((int) args[0])
else if args[0].type == double:
foo((double) args[0])
else:
raise "Bad arguments to foo"
Unfortunately there are serious problems with this approach as
well. First, the addition of dynamic dispatch code introduces a
performance hit on the execution time of overloaded methods since the
arguments to each method call have to first be examined to figure out
which function to dispatch. Although the sample code above doesn't
look too bad, this procedure may involve interaction with the SWIG
type-checker, typemaps (a SWIG customization scheme), and other more
advanced parts of the interpreter. A more nasty problem has to do
with functions that can accept the same type of scripting object. For
example, if you have this,
the foo(double) function will probably accept both a scripting language integer and a floating point number as an argument. As a result, it's possible for the foo(double) function to hide the integer function foo(int) if arguments aren't checked in the correct order. For instance, if you switch the order of the two functions in the interface file, does foo(int) suddenly become unavailable? To deal with this problem, you might decide to make all of the overloaded functions additionally available through name mangling. However, that now introduces all of the problems of name mangling plus all of the problems of dynamic dispatch!void foo(int); void foo(double);
The bottom line is that even though some kind of dynamic dispatch scheme may be the "best" way to support overloading, it is difficult to implement and it has some serious shortcomings including performance, hiding of functions, and possibly poor interaction with some of SWIG's customization features.
wrap_foo_i(args) {
...
foo((int) arg[0]);
...
}
wrap_foo_d(args) {
...
foo((double) arg[0]);
...
}
wrap_foo_BSi(args) {
...
foo((Bar *) arg[0], (Spam *) arg[1], (int) arg[2]);
...
}
Next, a top-level wrapper could be written like this:
wrap_foo(args) {
if (wrap_foo_i(args) == SUCCESS) return SUCCESS;
if (wrap_foo_d(args) == SUCCESS) return SUCCESS;
if (wrap_foo_BSi(args) == SUCCESS) return SUCCESS;
return ERROR, "No matching function foo";
}
Like dynamic dispatch, this solution suffers from a
performance penalty from trying to start the execution of each
possible function. In fact, the impact may be worse since the only
way to determine the proper function is to try all possibilities until
no errors occur (dynamic dispatch could make more intelligent
choices). Another problem is that a function might throw an ERROR for
a different reason than improper arguments (maybe the arguments were
okay, but something happened during execution). Therefore, you would
need to have some kind of special error condition to indicate an error
in argument conversion. A more subtle problem arises with languages such as
Ruby and Perl that handle errors by executing a longjmp() to return control
back to the interpreter (in which case, the above approach won't work like we want).
Finally, making this approach work with inheritance and all
of SWIG's customization options is also problematic.
Of all of the schemes mentioned, trial execution is the most likely feature that might be added to SWIG in the future. However, no such support is planned at this time.
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,
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:%rename(foo) bar;
/* 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:
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:%module foo /* Rename these overloaded functions */ %rename(foo_i) foo(int); %rename(foo_d) foo(double); %include "header.h"
%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):
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).%rename(foo_i) *::foo(int); // Only rename foo(int) if it appears in a class.
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:
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: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 )
%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:
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.%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
A few implementation notes about the enhanced %rename directive and %ignore:
%rename(bar) ::foo; // Rename foo to bar in global scope only %rename(bar) Spam::foo; // Rename foo to bar in class Spam only %rename(bar) *::foo; // Rename foo in classes only
and this%rename(bar) foo; %rename(foo_i) Spam::foo(int); %rename(Foo) Spam::foo;
(the declarations are not stored in a linked list and order has no importance). Of course, a repeated %rename directive will change the setting for a previous %rename directive if exactly the same name, scope, and parameters are supplied.%rename(Foo) Spam::foo; %rename(bar) foo; %rename(foo_i) Spam::foo(int);
class Foo {
public:
...
void bar();
...
};
the declaration %rename(name) Foo::bar() only applies to the unqualified member bar().
However, an often overlooked C++ feature is that classes can define two different overloaded members
that differ only in their qualifiers, like this:
class Foo {
public:
...
void bar(); // Unqualified member
void bar() const; // Qualified member (OK)
...
};
In this case, the renaming operator would only apply to the first
method. If you wanted to rename the qualified member function, use
%rename(name) Foo::bar() const instead. Similarly, if you
merely wanted to ignore one of the declarations, use %ignore
with the full qualification. For example, the following directive
would tell SWIG to ignore the const version of bar()
above:
%ignore Foo::bar() const; // Ignore bar() const, but leave other bar() alone
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:
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:%rename(__add__) Complex::operator+;
_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:
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:>>> a = Complex(3,4) >>> b = Complex(5,2) >>> c = a + b # Invokes __add__ method
The resulting scripting interface might work like this:%rename(add) operator+;
All of the techniques described to deal with overloaded functions also apply to operators. For example:a = Complex(3,4) b = Complex(5,2) c = a.add(b) # Call a.operator+(b)
The last part of this example illustrates how multiple definitions of the operator- method might be handled.%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 -
Handling operators in this manner is mostly straightforward. However, there are a few subtle issues to keep in mind:
class Complex {
public:
friend Complex operator+(Complex &, double);
};
Complex operator+(Complex &, double);
SWIG simply ignores all friend declarations. Furthermore, it
doesn't know how to associate the associated operator+ with
the class (because it's not a member of the class).
It's still possible to make a wrapper for this operator, but you'll have to handle it like a normal function. For example:
%rename(add_complex_double) operator+(Complex &, double);
%module vector
%{
#include "vector.h"
%}
class Vector {
public:
double x,y,z;
Vector();
~Vector();
... bunch of C++ methods ...
%extend {
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.
The %extend directive follows all of the same conventions as its use with C structures. Please refer to the SWIG Basics chapter for further details.>>> >>> v = Vector(); >>> v.x = 3 >>> v.y = 4 >>> v.z = 0 >>> print(v) [ 3.0, 4.0, 0.0 ] >>>
Compatibility note: The %extend directive is a new name for the %addmethods directive. Since %addmethods could be used to extend a structure with more than just methods, a more suitable directive name has been chosen.
There are some restrictions on the use of non-type arguments. Specifically, they have to be simple literals and not expressions. For example:void foo(vector<int> *a, int n); void bar(list<int,100> *x);
The type system is smart enough to figure out clever games you might try to play with typedef. For instance, consider this code:void bar(list<int,100> *x); // OK void bar(list<int,2*50> *x); // Illegal
In this case, vector<Integer> is exactly the same type as vector<int>. The wrapper for foo() will accept either variant.typedef int Integer; void foo(vector<int> *x, vector<Integer> *y);
Starting with SWIG-1.3.7, simple C++ template declarations can also be wrapped. SWIG-1.3.12 greatly expands upon the earlier implementation. 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 template definition:
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.
One way to create wrappers for a specific template instantiation is to simply provide an expanded version of the class directly like this:
%rename(intList) List<int>; // Rename to a suitable identifier
class List<int> {
private:
int *data;
int nitems;
int maxitems;
public:
List(int max);
~List();
void append(int obj);
int length();
int get(int n);
};
The %rename directive is needed to give the template class an appropriate identifier
name in the target language (most languages would not recognize C++ template syntax as a valid
class name). The rest of the code is the same as what would appear in a normal
class definition.
Since manual expansion of templates gets old in a hurry, the %template directive can be used to create instantiations of a template class. Semantically, %template is simply a shortcut---it expands template code in exactly the same way as shown above. Here are some examples:
The argument to %template() is the name of the instantiation in the target language. The name you choose should not conflict with any other declarations in the interface file with one exception---it is okay for the template name to match that of a typedef declaration. For example:/* Instantiate a few different versions of the template */ %template(intList) List<int>; %template(doubleList) List<double>;
SWIG can also generate wrappers for function templates using a similar technique. For example:%template(intList) List<int>; ... typedef List<int> intList; // OK
// Function template
template<class T> 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.
The number of arguments supplied to %template should match that in the original template definition. Template default arguments are supported. For example:
template vector<typename T, int max=100> class vector {
...
};
%template(intvec) vector<int>; // OK
%template(vec1000) vector<int,1000>; // OK
The %template directive should not be used to wrap the same template instantiation more than once in the same scope. This will generate an error. For example:
%template(intList) List<int>; %template(Listint) List<int>; // Error. Template already wrapped.
This error is caused because the template expansion results in two identical classes with the same name. This generates a symbol table conflict. Besides, it probably more efficient to only wrap a specific instantiation only once in order to reduce the potential for code bloat.
Since the type system knows how to handle typedef, it is generally not necessary to instantiate different versions of a template for typenames that are equivalent. For instance, consider this code:
In this case, vector<Integer> is exactly the same type as vector<int>. Any use of Vector<Integer> is mapped back to the instantiation of vector<int> created earlier. Therefore, it is not necessary to instantiate a new class for the type Integer (doing so is redundant and will simply result in code bloat).%template(intList) vector<int>; typedef int Integer; ... void foo(vector<Integer> *x);
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 should generate an warning message.
Occassionally, you may need to tell SWIG about base classes that are defined by templates, but which aren't supposed to be wrapped. Since SWIG is not able to automatically instantiate templates for this purpose, you must do it manually. To do this, simply use %template with no name. For example:
// Instantiate traits<double,double>, but don't wrap it. %template() traits<double,double>;
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) ...
The SWIG template mechanism does support specialization. For instance, if you define a class like this,
template<> class List<int> {
private:
int *data;
int nitems;
int maxitems;
public:
List(int max);
~List();
void append(int obj);
int length();
int get(int n);
};
then SWIG will use this code whenever the user expands List<int>. In practice,
this may have very little effect on the underlying wrapper code since
specialization is often used to provide slightly modified method bodies (which
are ignored by SWIG). However, special SWIG
directives such as %typemap, %extend, and so forth can be attached
to a specialization to provide customization for specific types.
Partial template specialization is partially supported by SWIG. For example, this code defines a template that is applied when the template argument is a pointer.
template<class T> class List<T*> {
private:
T *data;
int nitems;
int maxitems;
public:
List(int max);
~List();
void append(int obj);
int length();
T get(int n);
};
SWIG should be able to handle most simple uses of partial specialization. However, it may fail
to match templates properly in more complicated cases. For example, if you have this code,
template<class T1, class T2> class Foo<T1, T2 *> { };
SWIG isn't able to match it properly for instantiations like Foo<int *, int *>.
This problem is not due to parsing, but due to the fact that SWIG does not currently implement all
of the C++ argument deduction rules.
Member function templates are supported. The underlying principle is the same as for normal templates--SWIG can't create a wrapper unless you provide more information about types. For example, a class with a member template might look like this:
class Foo {
public:
template<class T> void bar(T x, T y) { ... };
...
};
To expand the template, simply use %template inside the class.
class Foo {
public:
template<class T> void bar(T x, T y) { ... };
...
%template(barint) bar<int>;
%template(bardouble) bar<double>;
};
Or, if you want to leave the original class definition alone, just do this:
class Foo {
public:
template<class T> void bar(T x, T y) { ... };
...
};
...
%extend Foo {
%template(barint) bar<int>;
%template(bardouble) bar<double>;
};
Note: because of the way that templates are handled, the %template directive
must always appear after the definition of the template to be expanded.
When used with members, the %template directive may be placed in another template class. Here is a slightly perverse example:
// A template
template<class T> class Foo {
public:
// A member template
template<class S> T bar(S x, S y) { ... };
...
};
// Expand a few member templates
%extend Foo {
%template(bari) bar<int>;
%template(bard) bar<double>;
};
// Create some wrappers for the template
%template(Fooi) Foo<int>;
%template(Food) Foo<double>;
Miraculously, you will find that each expansion of Foo has member
functions bari() and bard() added.
A common use of member templates is to define constructors for copies and conversions. For example:
template<class T1, class T2> struct pair {
T1 first;
T2 second;
pair() : first(T1()), second(T2()) { }
pair(const T1 &x, const T2 &y) : first(x), second(y) { }
template<class U1, class U2> pair(const pair<U1,U2> &x) : first(x.first),second(x.second) { }
};
This declaration is perfectly acceptable to SWIG, but the constructor template will be ignored
unless you explicitly expand it. To do that, you could expand a few versions of the constructor
in the template class itself. For example:
%extend pair {
%template(pair) pair<T1,T2>; // Generate default copy constructor
};
When using %extend in this manner, notice how you can still use the template parameters in
the original template definition.
Alternatively, you could expand the constructor template in selected instantiations. For example:
// Instantiate a few versions
%template(pairii) pair<int,int>;
%template(pairdd) pair<double,double>;
// Create a conversion constructor from int to double
%extend pair<double,double> {
%template(pairdd_from_pairii) pair<int,int>; // Conversion constructor
};
Admittedly, this isn't very pretty or automatic. However, it's probably
better than nothing--well, maybe.
If all of this isn't quite enough and you really want to make someone's head explode, SWIG directives such as %rename, %extend, and %typemap can be included directly in template definitions. For example:
// File : list.h
template<class T> class List {
...
public:
%rename(__getitem__) get(int);
List(int max);
~List();
...
T get(int index);
%extend {
char *__str__() {
/* Make a string representation */
...
}
}
};
In this example, the extra SWIG directives are propagated to every template
instantiation.
It is also possible to separate these declarations from the template class. For example:
%rename(__getitem__) List::get;
%extend List {
char *__str__() {
/* Make a string representation */
...
}
/* Make a copy */
T *__copy__() {
return new List<T>(*self);
}
};
...
template<class T> class List {
...
public:
List() { };
...
};
When %extend is decoupled from the class definition, it is legal to use the same template parameters as provided in the class definition. These are replaced when the template is expanded. In addition, the %extend directive can be used to add additional methods to a specific instantiation. For example:
%template(intList) List<int>;
%extend List<int> {
void blah() {
printf("Hey, I'm an List<int>!\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 does not perform 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:
template<class T> void foo(T x) { };
template<class T> void foo(T x, T y) { }; // Error. foo already defined.
This will generate a name conflict error message in SWIG. To silence the error message, use %ignore:
In this case, %template will only work with the first definition. To create a wrapper for the second definition, just do it manually:%ignore foo(T,T);
%name(foo2int) void foo<int>(int x, int y);
Compatibility Note: The first implementation of template support relied heavily on macro expansion in the preprocessor. Templates have been more tightly integrated into the parser and type system in SWIG-1.3.12 and the preprocessor is no longer used. Code that relied on preprocessing features in template expansion will no longer work. However, SWIG still allows the # operator to be used to generate a string from a template argument.
Compatibility Note: In earlier versions of SWIG, the %template directive introduced a new class name. This name could then be used with other directives. For example:
%template(vectori) vector<int>;
%extend vectori {
void somemethod() { }
};
This behavior is no longer supported. Instead, you should use the original template name
as the class name. For example:
%template(vectori) vector<int>;
%extend vector<int> {
void somemethod() { }
};
Similar changes apply to typemaps and other customization features.
namespace math {
double sin(double);
double cos(double);
class Complex {
double im,re;
public:
...
};
...
};
Members of the namespace are accessed in C++ by prepending the namespace prefix
to names. For example:
At this level, namespaces are relatively easy to manage. However, things start to get very ugly when you throw in the other ways a namespace can be used. For example, selective symbols can be exported from a namespace with using.double x = math::sin(1.0); double magitude(math::Complex *c); math::Complex c; ...
Similarly, the contents of an entire namespace can be made available like this:using math::Complex; double magnitude(Complex *c); // Namespace prefix stripped
Alternatively, a namespace can be aliased:using namespace math; double x = sin(1.0); double magnitude(Complex *c);
Using combinations of these features, it is possible to write head-exploding code like this:namespace M = math; double x = M::sin(1.0); double magnitude(M::Complex *c);
namespace A {
class Foo {
};
}
namespace B {
namespace C {
using namespace A;
}
typedef C::Foo FooClass;
}
namespace BIGB = B;
namespace D {
using BIGB::FooClass;
class Bar : public FooClass {
}
};
class Spam : public D::Bar {
};
void evil(A::Foo *a, B::FooClass *b, B::C::Foo *c, BIGB::FooClass *d,
BIGB::C::Foo *e, D::FooClass *f);
Given the possibility for such perversion, it's hard to imagine how
every C++ programmer might want such code wrapped into the target
language. Clearly this code defines three different classes. However, one
of those classes is accessible under at least six different class names!
SWIG fully supports C++ namespaces in its internal type system and class handling code. If you feed SWIG the above code, it will be parsed correctly, it will generate compilable wrapper code, and it will produce a working scripting language module. However, the default wrapping behavior is to flatten namespaces in the target language. This means that the contents of all namespaces are merged together in the resulting scripting language module. For example, if you have code like this,
%module foo
namespace foo {
void bar(int);
void spam();
}
namespace bar {
void blah();
}
then SWIG simply creates three wrapper functions bar(),
spam(), and blah() in the target language. SWIG
does not prepend the names with a namespace prefix nor are the
functions packaged in any kind of nested scope.
There is some rationale for taking this approach. Since C++ namespaces are often used to define modules in C++, there is a natural correlation between the likely contents of a SWIG module and the contents of a namespace. For instance, it would not be unreasonable to assume that a programmer might make a separate extension module for each C++ namespace. In this case, it would be redundant to prepend everything with an additional namespace prefix when the module itself already serves as a namespace in the target language. Or put another way, if you want SWIG to keep namespaces separate, simply wrap each namespace with its own SWIG interface.
Because namespaces are flattened, it is possible for symbols defined in different namespaces to generate a name conflict in the target language. For example:
namespace A {
void foo(int);
}
namespace B {
void foo(double);
}
When this conflict occurs, you will get an error message that resembles this:
To resolve this error, simply use %rename to disambiguate the declarations. For example:example.i:26. Error. 'foo' is multiply defined in the generated module. example.i:23. Previous declaration of 'foo'
%rename(B_foo) B::foo;
...
namespace A {
void foo(int);
}
namespace B {
void foo(double); // Gets renamed to B_foo
}
Similarly, %ignore can be used to ignore declarations.
using declarations do not have any effect on the generated wrapper code. They are ignored by SWIG language modules and they do not result in any code. However, these declarations are used by the internal type system to track type-names. Therefore, if you have code like this:
namespace A {
typedef int Integer;
}
using namespace A;
void foo(Integer x);
SWIG knows that Integer is the same as A::Integer which
is the same as int.
Namespaces may be combined with templates. If necessary, the %template directive can be used to expand a template defined in a different namespace. For example:
namespace foo {
template<typename T> max(T a, T b) { return a > b ? a : b; }
}
using foo::max;
%template(maxint) max<int> // Okay.
%template(maxfloat) foo::max<float>; // Okay (qualified name).
namespace bar {
using namespace foo;
%template(maxdouble) max<double>; // Okay.
}
The combination of namespaces and other SWIG directives may introduce subtle scope-related problems.
The key thing to keep in mind is that all SWIG generated wrappers are produced
in the global namespace. Symbols from other namespaces are always accessed using fully
qualified names---names are never imported into the global space unless the interface happens to
do so with a using declaration. In almost all cases, SWIG adjusts typenames and symbols
to be fully qualified. However, this is not done in code fragments such as function bodies,
typemaps, exception handlers, and so forth. For example, consider the following:
namespace foo {
typedef int Integer;
class bar {
public:
...
};
}
%extend foo::bar {
Integer add(Integer x, Integer y) {
Integer r = x + y; // Error. Integer not defined in this scope
return r;
}
};
In this case, SWIG correctly resolves the added method parameters and return type to
foo::Integer. However, since function bodies aren't parsed and such code is
emitted in the global namespace, this code produces a compiler error about Integer.
To fix the problem, make sure you use fully qualified names. For example:
%extend foo::bar {
Integer add(Integer x, Integer y) {
foo::Integer r = x + y; // Ok.
return r;
}
};
Note: SWIG does not propagate using declarations to the resulting wrapper code. If these declarations appear in an interface, they should also appear in any header files that might have been included in a %{ ... %} section. In other words, don't insert extra using declarations into a SWIG interface unless they also appear in the underlying C++ code.
Note: Code inclusion directives such as %{ ... %} or %inline %{ ... %} should not be placed inside a namespace declaration. The code emitted by these directives will not be enclosed in a namespace and you may get very strange results. If you need to use namespaces with these directives, consider the following:
// Good version
%inline %{
namespace foo {
void bar(int) { ... }
...
}
%}
// Bad version. Emitted code not placed in namespace.
namespace foo {
%inline %{
void bar(int) { ... } /* I'm bad */
...
%}
}
Note: When the %extend directive is used inside a namespace, the namespace name is included in the generated functions. For example, if you have code like this,
namespace foo {
class bar {
public:
%extend {
int blah(int x);
};
};
}
the added method blah() is mapped to a function int foo_bar_blah(foo::bar *self, int x).
This function resides in the global namespace.
Note: Although namespaces are flattened in the target language, the SWIG generated wrapper code observes the same namespace conventions as used in the input file. Thus, if there are no symbol conflicts in the input, there will be no conflicts in the generated code.
Note: The flattening of namespaces is only intended to serve as a basic namespace implementation. Since namespaces are a new addition to SWIG, none of the target language modules are currently programmed with any namespace awareness. In the future, language modules may or may not provide more advanced namespace support.
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.double do_op(Object *o, double (Object::*callback)(double,double)); extern double (Object::*fooptr)(double,double); %constant double (Object::*FOO)(double,double) = &Object::foo;
When pointers to members are supported, the pointer value might appear as a special string like this:
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.>>> print example.FOO _ff0d54a800000000_m_Object__f_double_double__double >>>
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.
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.
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:
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).>>> bar(foo()) # Okay >>>
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.