This is only a partial list of options. A full listing of options can be obtained by invoking "swig -help". Each target language may have additional options which can be displayed using "swig -lang -help" where -lang is one of the target languages above.swig <options> filename -tcl Generate Tcl wrappers -tcl8 Generate Tcl 8.0 wrappers -perl Generate Perl5 wrappers -python Generate Python wrappers -perl4 Generate Perl4 wrappers -guile Generate Guile wrappers -dascii ASCII documentation -dlatex LaTeX documentation -dhtml HTML documentation -dnone No documentation -c++ Enable C++ handling -objc Enable Objective-C handling. -Idir Set SWIG include directory -lfile Include a SWIG library file. -c Generate raw wrapper code (omit supporting code) -v Verbose mode (perhaps overly verbose) -o outfile Name of output file -d docfile Set name of documentation file (without suffix) -module name Set name of SWIG module -Dsymbol Define a symbol -version Show SWIG's version number -help Display all options
The name of the module (if supplied) must always appear before the first C declaration or be supplied on the SWIG command line using the -module option (When the module name is specified on the command line, it will override any module name present in a file). Everything inside the %{,%} block is copied verbatim into the resulting output file. The %{,%} block is optional, but most interface files use one to include the proper header files.%module mymodule %{ #include "myheader.h" %} // Now list ANSI C variable and function declarations
All other C preprocessor directives are ignored by SWIG (including macros created using #define).
Many of these limitations may be eliminated in future releases. It is worth noting that many of the problems associated with complex declarations can sometimes be fixed by clever use of typedef.
If you are not sure whether SWIG can handle a particular declaration, the best thing to do is try it and see. SWIG will complain loudly if it can't figure out what's going on. When errors occur, you can either remove the offending declaration, conditionally compile it out (SWIG defines a symbol SWIG that can be used for this), or write a helper function to work around the problem.
will create two commands called "sin" and "strcmp", a global variable "My_variable", and two constants "STATUS" and "VERSION". Things work about like you would expect. For example, in Tcl :%module example extern double sin(double x); extern int strcmp(const char *, const char *); extern int My_variable; #define STATUS 50 const char *VERSION="1.1";
The main concern when working with simple functions is SWIG's treatment of basic datatypes. This is described next.% sin 3 5.2335956 % strcmp Dave Mike -1 % puts $My_variable 42 % puts $STATUS 50 % puts $VERSION 1.1
int short long unsigned signed unsigned short unsigned long unsigned char signed char bool
Scripting languages usually only support a single integer type that corresponds to either the int or long datatype in C. When converting from C, all of the above datatypes are cast into the representation used by the target scripting language. Thus, a 16 bit short in C may be converted to a 32 bit integer. When integers are converted from the scripting language back into C, the value will be cast into the appropriate type. The value will be truncated if it is too large to fit into the corresponding C datatype. This truncation is not currently checked.
The unsigned char and signed char datatypes are special cases that are treated as integers by SWIG. Normally, the char datatype is mapped as an ASCII string.
The bool datatype is cast to and from an integer value of 0 and 1.
Some care is in order for large integer values. Most scripting language use 32 bit integers so mapping a 64 bit long integer may lead to truncation errors. Similar problems may arise with 32 bit unsigned integers that may show up as negative numbers. As a rule of thumb, the int datatype and all variations of char and short datatypes are safe to use. For unsigned int and long datatypes, you should verify the correct operation of your program after wrapping it with SWIG.
float double
Floating point numbers are mapped to and from the natural representation of floats in the target language. This is almost always a double except in Tcl 7.x which uses character strings. The rarely used datatype of "long double" is not supported by SWIG.
The char * datatype is assumed to be a NULL-terminated ASCII string. SWIG maps this into a character string in the target language. SWIG converts character strings in the target language to NULL terminated strings before passing them into C/C++. It is illegal for these strings to have embedded NULL bytes although there are ways to work around this problem.
The signed char and unsigned char datatypes are mapped into integer values. The following example illustrates the mapping of char datatypes.
%{ #include <stdio.h> #include <ctype.h> #include <string.h> signed char sum(signed char a, signed char b) { return a+b;} %} int strcmp(char *, char *); char toupper(char); signed char sum(signed char a, signed char b);
A Tcl script using these functions (and the resulting output) might be as follows.
tclsh > strcmp Mike John 1 tclsh > toupper g G tclsh > sum 17 -8 9
will result in a scripting language variable that can be used as follows :%module example double foo;
Whenever this "special" variable is used, the underlying C global variable will be accessed. As it turns out, working with global variables is one of the most tricky aspects of SWIG. Whenever possible, you should try to avoid the use of globals. Fortunately, most modular programs make limited (or no) use of globals.# Tcl set foo [3.5] ;# Set foo to 3.5 puts $foo ;# Print the value of foo # Python cvar.foo = 3.5 ;# Set foo to 3.5 print cvar.foo ;# Print value of foo # Perl $foo = 3.5; ;# Set foo to 3.5 print $foo,"\n"; ;# Print value of foo
In #define declarations, the type of a constant is inferred by syntax or can be explicitly set using a cast. For example, a number with a decimal point is assumed to be floating point. When no explicit value is available for a constant, SWIG will use the value assigned by the C compiler. For example, no values are given to the months enumeration, but this is no problem---SWIG will use whatever the C compiler picks.#define I_CONST 5 // An integer constant #define F_CONST 3.14159 // A Floating point constant #define S_CONST "hello world" // A string constant #define NEWLINE '\n' // Character constant #define MODE DEBUG // Sets MODE to DEBUG. // DEBUG is assumed to be an // int unless declared earlier enum boolean {NO=0, YES=1}; enum months {JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC}; const double PI 3.141592654; #define F_CONST (double) 5 // A floating pointer constant with cast #define PI_4 PI/4 #define FLAGS 0x04 | 0x08 | 0x40
The use of constant expressions is allowed, but SWIG does not evaluate them. Rather, it passes them through to the output file and lets the C compiler perform the final evaluation (SWIG does perform a limited form of type-checking however).
For enumerations, it is critical that the original enum definition be included somewhere in the interface file (either in a header file or in the %{,%} block). SWIG only translates the enumeration into code needed to add the constants to a scripting language. It needs the original enumeration declaration to retrieve the correct enum values.
int * double *** char **
can be used freely in an interface file. SWIG encodes pointers into a representation containing the actual value of the pointer and a string representing the datatype. Thus, the SWIG representation of the above pointers (in Tcl), might look like the following :
_10081012_int_p _1008e124_double_ppp _f8ac_char_pp
A NULL pointer is represented by the string "NULL" or the value 0 encoded with type information.
All pointers are treated as opaque objects by SWIG. A pointer may be returned by a function and passed around to other C functions as needed. For all practical purposes, the scripting language interface works in exactly the same way as you would write a C program (well, with a few limitations).
The scripting language representation of a pointer should never be manipulated directly (although nothing prevents this). SWIG does not normally map pointers into high-level objects such as associative arrays or lists (for example, it might be desirable to convert an int * into an list of integers). There are several reasons for this :
As it turns out, you can remap any C datatype to behave in new ways so these rules are not set in stone. Interested readers should look at the chapter on typemaps.
Strict type checking is the recommended default since is the most reliable and most closely follows the type checking rules of C. In fact, at this time, the other two modes should be considered to be outdated SWIG features that are supported, but no longer necessary.-strict 0 No type-checking (living on the edge) -strict 1 Generate warning messages (somewhat annoying) -strict 2 Strict type checking (the default)
By default, SWIG allows "NULL" pointers to be passed to C/C++. This has the potential to crash code and cause other problems if you are not careful. Checks can be placed on certain values to prevent this but this requires the use of typemaps (described in later chapters).
Like C, it should also be noted that functions involving void pointers can accept any kind of pointer object.
All complex datatypes are pointers
In other words, SWIG manipulates everything else by reference. This model makes sense because most C/C++ programs make heavy use of pointers and we can use the type-checked pointer mechanism already present for handling pointers to basic datatypes.
While all of this probably sounds complicated, it's really quite simple. Suppose you have an interface file like this :
In this file, SWIG doesn't know what a FILE is, but it's used as a pointer, so it doesn't really matter what it is. If you wrapped this module into Python, you could use the functions just like you would expect :%module fileio FILE *fopen(char *, char *); int fclose(FILE *); unsigned fread(void *ptr, unsigned size, unsigned nobj, FILE *); unsigned fwrite(void *ptr, unsigned size, unsigned nobj, FILE *); void *malloc(int nbytes); void free(void *);
In this case f1, f2, and buffer are all opaque objects containing C pointers. It doesn't matter what value they contain--our program works just fine without this knowledge.# Copy a file def filecopy(source,target): f1 = fopen(source,"r") f2 = fopen(target,"w") buffer = malloc(8192) nbytes = fread(buffer,8192,1,f1) while (nbytes > 0): fwrite(buffer,8192,1,f2) nbytes = fread(buffer,8192,1,f1) free(buffer)
void matrix_multiply(Matrix *a, Matrix *b, Matrix *c);
SWIG has no idea what a "Matrix" is so it will assume that you know what you are doing and map it into a pointer. This makes perfect sense because the underlying C function is using pointers in the first place. Unlike C or C++, SWIG does not actually care whether Matrix has been previously defined in the interface file or not. While this may sound strange, it makes it possible for SWIG to generate interfaces from only partial information. In many cases, you may not care what a Matrix really is as long as you can pass references to one around in the scripting language interface. The downside to this relaxed approach is that typos may go completely undetected by SWIG. You can also end up shooting yourself in the foot, but presumably you've passed your programming safety course if you've made it this far.
As a debugging tool, SWIG will report a list of used, but undefined datatypes, if you run it with the -stat option.
[beazley@guinness SWIG1.1b6]$ swig -stat matrix.i Making wrappers for Tcl Wrapped 1 functions Wrapped 0 variables Wrapped 0 constants The following datatypes were used, but undefined. Matrix [beazley@guinness SWIG1.1b6]$
This makes SWIG treat size_t like an unsigned int. Use of typedef is fairly critical in most applications. Without it, SWIG would consider size_t to be a complex object (which would be incorrectly converted into a pointer).typedef unsigned int size_t;
double dot_product(Vector a, Vector b);
SWIG will transform this function call into the equivalent of the following :
double wrap_dot_product(Vector *a, Vector *b) { return dot_product(*a,*b); }
In the scripting language, dot_product will now take references to Vectors instead of Vectors, although you may not notice the change.
This function is returning a complex object, yet SWIG only likes to work with references. Clearly, something must be done with the return result, or it will be lost forever. As a result, SWIG transforms this function into the following code :Vector cross(Vector v1, Vector v2);
Vector *wrap_cross(Vector *v1, Vector *v2) { Vector *result; result = (Vector *) malloc(sizeof(Vector)); *(result) = cross(*v1,*v2); return result; }
or if using C++ :
Vector *wrap_cross(Vector *v1, Vector *v2) { Vector *result = new Vector(cross(*v1,*v2)); // Uses default copy constructor return result; }
SWIG is forced to create a new object and return a reference to it. It is up to the user to delete the returned object when it is no longer in use. When used improperly, this can lead to memory leaks and other problems. Personally, I'd rather live with a potential memory leak than forbid the use of such a function. Needless to say, some care is probably in order (you need to be aware of this behavior in any case).
Vector unit_i;
gets mapped to a pair of set/get functions like this :
Vector *unit_i_get() { return &unit_i; } Vector *unit_i_set(Vector *value) { unit_i = *value; return &unit_i; }
Returning a reference to the variable makes it accessible like any other object of this type. When setting the value, we simply make a copy of some other Vector reference. Again some caution is in order. A global variable created in this manner will show up as a reference in the target scripting language. It would be an extremely bad idea to free or destroy such a reference. Similarly, one can run into problems when copying complex C++ objects in this manner. Fortunately, in well-written modular code, excessive use (or abuse) of global variables is rare.
int foobar(int a[40]); void grok(char *argv[]); void transpose(double a[20][20]);
will be processed as if they were declared like this:
int foobar(int *a); void grok(char **argv); void transpose(double (*a)[20]);
Multi-dimensional arrays are transformed into a single pointer since a[][] and **a are not the same thing (even though they can be used in similar ways). Rather, a[][] is mapped to *a, where *a is the equivalent of &a[0][0]. The reader is encouraged to dust off their C book and look at the section on arrays before using them with SWIG.
Be aware that use of arrays may cause compiler warnings or errors when compiling SWIG generated modules. While every attempt has been made to eliminate these problems, handling of arrays can be somewhat problematic due to the subtle differences between an array and a pointer.
// File : interface.i int a; // Can read/write %readonly int b,c,d // Read only variables %readwrite double x,y // read/write
The %readonly directive enables read-only mode until it is explicitly disabled using the %readwrite directive.
SWIG still calls the correct C functions, but in this case the function print() will really be called "my_print()" in the scripting language.// interface.i %name(my_print) extern void print(char *); %name(foo) extern int a_really_long_and_annoying_name;
A more powerful renaming operation can be performed with the %rename directive as follows :
%rename applies a renaming operation to all future occurrences of a name. The renaming applies to functions, variables, class and structure names, member functions, and member data. For example, if you had two-dozen C++ classes, all with a member function named `print' (which is a keyword in Python), you could rename them all to `output' by specifying :%rename oldname newname;
%rename print output; // Rename all `print' functions to `output'
SWIG does not perform any checks to see if the functions it adds are already defined in the target scripting language. However, if you are careful about namespaces and your use of modules, you can usually avoid these problems.
The localtime() function takes a pointer to a time_t value, but we have forced it to take a value instead in order to match up nicely with the return value of the time() function. When used in Perl, this allows us to do something like this :// interface.i %{ #include <time.h> %} typedef long time_t; time_t time(time_t *t); struct tm *localtime(%val time_t *t); char *asctime(struct tm *);
Internally, the %val directive creates a temporary variable. The argument value is stored in this variable and a function call is made using a pointer to the temporary variable. Of course, if the function returns a value in this temporary variable, it will be lost forever.$t = time(0); $tm = localtime($t); # Note passing $t by value here print $asctime($tm);
To specify a default argument, simply specify it the function prototype as shown. SWIG will generate wrapper code in which the default arguments are optional. For example, this function could be used in Tcl as follows :int plot(double x, double y, int color=WHITE);
While the ANSI C standard does not specify default arguments, default arguments used in a SWIG generated interface work with both C and C++.% plot -3.4 7.5 # Use default value % plot -3.4 7.5 10 # set color to 10 instead
void do_operation(double (*op)(double,double), double a, double b);
should be handled as follows :
SWIG understands both the typedef declaration and the later function call. It will treat OP_FUNC just like any other complex datatype. In order for this approach to work, it is necessary that the typedef declaration be present in the original C code--otherwise, the C compiler will complain. If you are building a separate interface file to an existing C program and do not want to make changes to the C source, you can also do the following :typedef double (*OP_FUNC)(double,double); void do_operation(OP_FUNC op, double a, double b);
// File : interface.i %typedef double (*OP_FUNC)(double,double); double do_operation(OP_FUNC op, double a, double b);
%typedef forces SWIG to generate a typedef in the C output code for you. This would allow the interface file shown to work with the original unmodified C function declaration.
Constants containing the addresses of C functions can also be created. For example, suppose you have the following callback functions :
The addresses of these functions could be installed as scripting language constants as follows :extern double op_add(double a, double b); extern double op_sub(double a, double b); extern double op_mul(double a, double b);
When wrapped, this would create the constants ADD,SUB, and MUL containing the addresses of C callback functions. We could then pass these to other C functions expecting such function pointers as arguments as shown (for Tcl) :// interface.i typedef double (*OP_FUNC)(double,double); ... const OP_FUNC ADD = op_add; const OP_FUNC SUB = op_sub; const OP_FUNC MUL = op_mul; ...
%do_operation $ADD 3 4 7 %
gets mapped into the following set of accessor functions :struct Vector { double x,y,z; }
double Vector_x_get(Vector *obj) { return obj->x; } double Vector_y_get(Vector *obj) { return obj->y; } double Vector_z_get(Vector *obj) { return obj->z; } double Vector_x_set(Vector *obj, double value) { obj->x = value; return value; } double Vector_y_set(Vector *obj, double value) { obj->y = value; return value; } double Vector_z_set(Vector *obj, double value) { obj->z = value; return value; }
When encountered, SWIG will assume that the name of the object is `Vector' and create accessor functions like before. If two different names are used like this :typedef struct { double x,y,z; } Vector;
the name `Vector' will still be used instead of "vector_struct".typedef struct vector_struct { double x,y,z; } Vector;
This results in the following accessor functions :%module mymodule ... struct Foo { char *name; ... }
char *Foo_name_get(Foo *obj) { return Foo->name; } char *Foo_name_set(Foo *obj, char *c) { if (obj->name) free(obj->name); obj->name = (char *) malloc(strlen(c)+1); strcpy(obj->name,c); return obj->name; }
This seems to work most of the time, but occasionally it's not always what you want. Typemaps can be used to change this behavior if necessary.
To eliminate the warning message, typemaps can be used, but this is discussed in a later chapter (and best reserved for experienced users). Otherwise, if you get this warning, it may be harmless.interface.i : Line 116. Warning. Array member will be read-only
When used with C code, SWIG will create two additional functions like this :%module mymodule ... struct Vector { Vector(); // Tell SWIG to create a C constructor ~Vector(); // Tell SWIG to create a C destructor double x,y,z; }
While C knows nothing about constructors and destructors, SWIG does---and it can automatically create some for you if you want. This only applies to C code--handling of C++ is handled differently.Vector *new_Vector() { return (Vector *) malloc(sizeof(Vector)); } void delete_Vector(Vector *v) { free(v); }
As an alternative to explicitly defining constructors and destructors, SWIG can also automatically generate them using either a command line option or a pragma. For example :
orswig -make_default example.i
This works with both C and C++.%module foo ... %pragma make_default // Make default constructors ... declarations ... %pragma no_default // Disable default constructors
You can make a Vector look alot like a class by doing the following in an interface file :/* file : vector.h */ ... typedef struct { double x,y,z; } Vector;
Now, when used with shadow classes in Python, you can do things like this :// file : vector.i %module mymodule %{ #include "vector.h" %} %include vector.h // Just grab original C header file %addmethods Vector { // Attach these functions to struct Vector Vector(double x, double y, double z) { Vector *v; v = (Vector *v) malloc(sizeof(Vector)); v->x = x; v->y = y; v->z = z; return v; } ~Vector() { free(self); } double magnitude() { return sqrt(self->x*self->x+self->y*self->y+self->z*self->z); } void print() { printf("Vector [%g, %g, %g]\n", self->x,self->y,self->z); } };
>>> v = Vector(3,4,0) # Create a new vector >>> print v.magnitude() # Print magnitude 5.0 >>> v.print() # Print it out [ 3, 4, 0 ] >>> del v # Destroy it
The %addmethods directive can also be used in the definition of the Vector structure. For example:
// file : vector.i %module mymodule %{ #include "vector.h" %} typedef struct { double x,y,z; %addmethods { Vector(double x, double y, double z) { ... } ~Vector() { ... } ... } } Vector;
Finally, %addmethods can be used to access externally written functions provided they follow the naming convention used in this example :
So why bother with all of this %addmethods business? In short, you can use it to make some pretty cool `object oriented' scripting language interfaces to C programs without having to rewrite anything in C++./* File : vector.c */ /* Vector methods */ #include "vector.h" Vector *new_Vector(double x, double y, double z) { Vector *v; v = (Vector *) malloc(sizeof(Vector)); v->x = x; v->y = y; v->z = z; return v; } void delete_Vector(Vector *v) { free(v); } double Vector_magnitude(Vector *v) { return sqrt(v->x*v->x+v->y*v->y+v->z*v->z); } // File : vector.i // Interface file %module mymodule %{ #include "vector.h" %} typedef struct { double x,y,z; %addmethods { double magnitude(); // This will call Vector_magnitude ... } } Vector;
When SWIG encounters this, it performs a structure splitting operation that transforms the declaration into the equivalent of the following:typedef struct Object { int objtype; union { int ivalue; double dvalue; char *strvalue; void *ptrvalue; } intRep; } Object;
SWIG will create an Object_intRep structure for use inside the interface file. Accessor functions will be created for both structures. In this case, functions like this would be created :typedef union { int ivalue; double dvalue; char *strvalue; void *ptrvalue; } Object_intRep; typedef struct Object { int objType; Object_intRep intRep; } Object;
Is it hairy? You bet. Does it work? Well, surprisingly yes. When used with Python and Perl5 shadow classes, it's even possible to access the nested members just like you expect :Object_intRep *Object_intRep_get(Object *o) { return (Object_intRep *) &o->intRep; } int Object_intRep_ivalue_get(Object_intRep *o) { return o->ivalue; } int Object_intRep_ivalue_set(Object_intRep *o, int value) { return (o->ivalue = value); } double Object_intRep_dvalue_get(Object_intRep *o) { return o->dvalue; } ... etc ...
# Perl5 script for accessing nested member $o = CreateObject(); # Create an object somehow $o->{intRep}->{ivalue} = 7 # Change value of o.intRep.ivalue
If you've got a bunch of nested structure declarations, it is certainly advisable to check them out after running SWIG. However, there is a good chance that they will work. If not, you can always remove the nested structure declaration and write your own set of accessor functions.
It is also important to note that most language modules may choose to build a more advanced interface. You may never use the low-level interface described here, although most of SWIG's language modules use it in some way or another.
This section describes SWIG's low-level access to C++ declarations. In many instances, this low-level interface may be hidden by shadow classes or an alternative calling mechanism (this is usually language dependent and is described in detail in later chapters).
The following C++ features are not currently supported :
Since SWIG's C++ support is a "work in progress", many of these limitations may be lifted in future releases. In particular, function overloading and nested classes, may be supported in the future. Operator overloading and templates are unlikely to be supported anytime in the near future, but I'm not going to rule out the possibility in later releases.
%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 are handled with respect to differences between C and C++. It also enables the detection of C++ keywords. Without the -c++ flag, SWIG will either issue a warning or a large number of syntax errors if it encounters any C++ code in an interface file.
If the original C++ class does not have any constructors or destructors, putting constructors and destructors in the SWIG interface file will cause SWIG to generate wrappers for the default constructor and destructor of an object.List * new_List(void) { return new List; } void delete_List(List *l) { delete l; }
Virtual member functions are treated in an identical manner since the C++ compiler takes care of this for us automatically.int List_search(List *obj, char *value) { return obj->search(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.int List_length_get(List *obj) { return obj->length; } int List_length_set(List *obj, int value) { obj->length = value; return value; }
class List { public: ... %readonly int length; %readwrite ... };
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++).
Generates the following set of constants in the target scripting language :class Swig { public: enum {ALE, LAGER, PORTER, STOUT}; };
Members declared as const are wrapped in a similar manner.Swig_ALE = Swig::ALE Swig_LAGER = Swig::LAGER Swig_PORTER = Swig::PORTER Swig_STOUT = Swig::STOUT
class Foo { public: double bar(double &a); }
will be accessed using a function like this :
Functions returning a reference will be mapped into functions returning pointers.double Foo_bar(Foo *obj, double *a) { obj->bar(*a); }
SWIG does not support private or protected inheritance (it will be parsed, but ignored).
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: 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 Perl5, we can now perform the following operations :
In our example, we have created Circle and Square objects. We can call member functions on each object by making calls to Circle_area, Square_area, and so on. However, we can can accomplish the same thing by simply using the Shape_area function on either object.beazley@slack% perl5.003 use shapes; $circle = shapes::new_Circle(7); $square = shapes::new_Square(10); print shapes::Circle_area($circle),"\n"; # Notice use of base class below print shapes::Shape_area($circle),"\n"; print shapes::Shape_area($square),"\n"; shapes::Shape_set_location($square,2,-3); print shapes::Shape_perimeter($square),"\n"; <ctrl-d> 153.93804004599999757 153.93804004599999757 100.00000000000000000 40.00000000000000000
However, SWIG can support instantiations of a template and types involving templates. For example, the following interface file would be legal :// File : list.h #define MAXITEMS 100 template<class T> class List { // Entire class is ignored by SWIG private: T *data; int nitems; public: List() { data = new T [MAXITEMS]; nitems = 0; } ~List() { delete [] data; }; void append(T obj) { if (nitems < MAXITEMS) { data[nitems++] = obj; } } int length() { return nitems; } T get(int n) { return data[n]; } };
The type "List<double>" becomes the datatype for the function parameter. In, Python it might appear like this :// SWIG interface involving a template %module example %{ #include "list.h" // Get Template definition %} // Now a function involving templates extern void PrintData(List<double> &l);
To create specific objects, you may need to supply helper functions such as the following :>>> print cl _80a2df8_List<double>_p >>>
%inline %{ // Helper function to create a List<double> List<double> *new_DoubleList() { return new List<double>; } %}
Specific templates can also be wrapped in a clever way using typedef. For example, the following would also work :
In this case, SWIG thinks that there is a class "DoubleList" with the methods supplied. It generates the appropriate code and everything works like you would expect (of course, in reality there is no such class). When the SWIG module is compiled, all of the methods get supplied by the original template class. A key thing to keep in mind when working with templates is that SWIG can only handle particular instantiations of a template (such as a list of double). More general support is not yet provided (but may be added someday).%module example %{ #include "list.h" typedef List<double> DoubleList; %} class DoubleList { public: DoubleList(); ~DoubleList(); void append(double); int length(); double get(int n); };
This will create the functions List_find, List_delete, and a function named new_ListSize for the overloaded constructor.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); };
The %name directive can be applied to all members including constructors, destructors, static functions, data members, and enumeration values.
The class name prefix can be changed by specifying
%name(newname) class List { ... }
%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.
The %addmethods directive follows all of the same conventions as its use with C structures.>>> >>> v = Vector(); >>> v.x = 3 >>> v.y = 4 >>> v.z = 0 >>> print(v) [ 3.0, 4.0, 0.0 ] >>>
As a rule of thumb, running SWIG on raw C++ header or source files is currently discouraged. Given the complexity of C++ parsing and limitations in SWIG's parser it will still take some time for SWIG's parser to evolve to a point of being able to safely handle most raw C++ files.
Needless to say, handling all of the possible cases is probably impossible. SWIG is certainly not guaranteed to work with every conceivable type of C++ program (especially those that use C++ in a maximal manner). Nor is SWIG claiming to build C++ interfaces in a completely "safe" manner. The bottom line is that effective use of C++ with SWIG requires that you know what you're doing and that you have a certain level of "moral flexibility" when it comes to the issue of building a useful scripting language interface.
Objective-C support is built using the same approach as used for C++ parsing. Objective-C interface definitions are converted into a collection of ANSI C accessor functions. These accessor functions are then wrapped by SWIG and turned into an interface.
To enable Objective-C parsing, SWIG should be given the -objc option (this option may be used in conjunction with the -c++ option if using Objective-C++). It may also be helpful to use the -o option to give the output file the .m suffix needed by many Objective-C compilers. For example :
Objective-C interfaces should also include the file `objc.i' as this contains important definitions that are common to most Objective-C programs.% swig -objc -o example_wrap.m example.i
%module list %{ #import "list.h" %} %include objc.i // Very simple list class @interface List : Object { int nitems; // Number of items in the list int maxitems; // Maximum number of items id *items; // Array holding the items } //------------------------- List methods -------------------------- // Create a new list + new; // Destroy the list - free; // Copy a list - copy; // Append a new item to the list - (void) append: (id) item; // Insert an item in the list - (void) insert: (id) item : (int) pos; // Delete an item from the list - remove: (int) pos; // Get an item from the list - get: (int) i; // Find an item in the list and return its index - (int) index: obj; // Get length of the list - (int) len; // Print out a list (Class method) + (void) print: (List *) l; @end
If the original Objective-C class does not have any constructors or destructors, putting them in the interface file will cause SWIG to generate wrappers for a default constructor and destructor (assumed to be defined in the object's base-class).List *new_List(void) { return (List *) [List new]; } void delete_List(List *l) { [l free]; }
If your Objective-C program uses a different naming scheme for constructors and destructors, you can tell SWIG about it using the following directive :
%pragma objc_new = "create" // Change constructor to `create' %pragma objc_delete = "destroy" // Change destructor to `destroy'
void List_append(List *l, id item) { [l append : item]; }
void List_print(List *l) { [List print : l]; }
%module example %{ #import "foo.h" %} // Sample use of a category in an interface @interface Foo (CategoryName) // Method declarations -bar : (id) i; @end
Although SWIG ignores protocols, protocol type-specifiers may be used. For example, these are legal declarations :
SWIG will carry the protocol lists through the code generation process so the resulting wrapper code compiles without warnings.%module example %interface Foo : Object <proto1, proto2> { } // Methods - Bar : (id <proto1,proto2>) i; @end
@interface List : Object { @public %name(size) int length; // Rename length to size } + new; - free; %name(add) -(void) append: (id) item; // Rename append to add @end
@interface List : Object { } ... bunch of Objective-C methods ... %addmethods { - (void) output { ... code to output a list ... } } @end
%addmethods works in exactly the same manner as it does for C and C++ (except that Objective-C syntax is allowed). Consult those sections for more details.
Certain aspects of Objective-C are not currently supported (protocols for instance). These limitations may be lifted in future releases.
#ifdef SWIG %module mymodule %{ #include "header.h" %} %include wish.i #endif ... normal C declarations here ...
Similarly, conditional compilation can be used to customize an interface. The following interface file can be used to build a Perl5 module that works with either static or dynamic linking :
However, it is not safe to use conditional compilation in the middle of a declaration. For example :%module mymodule %{ #include "header.h" %} ... Declarations ... #ifdef STATIC %include perlmain.i // Include code for static linking #endif
This fails because the SWIG parser is not equipped to handle conditional compilation directives in an arbitrary location (like the C preprocessor). For files that make heavy use of the C preprocessor like this, it may be better to run the header file through the C preprocessor and use the output as the input to SWIG.double foo( #ifdef ANSI_ARGS double a, double b #endif );
Symbols can also be defined using #define with no arguments. For example :swig -perl5 -static -DSTATIC interface.i
%module mymodule #define STATIC ... etc ...
For the purposes of conditional compilation, one should not assign values to symbols. If this is done, SWIG interprets the #define as providing the definition of a scripting language constant.
#if defined(SYMBOL) ... #elif !defined(OTHERSYMBOL) ... #endif
The C preprocessor version supports any constant integral expression as an argument to #if, but SWIG does not yet contain an expression evaluator so this is not currently supported. As a result, declarations such as the following don't yet work :
#if (defined(foo) || defined(bar)) ... #endif
Interface files can look at these symbols as necessary to change the way in which an interface is generated or to mix SWIG directives with C code. These symbols are also defined within the C code generated by SWIG (except for the symbol `SWIG' which is only defined within the SWIG compiler).SWIG Always defined when SWIG is processing a file SWIGTCL Defined when using Tcl SWIGTCL8 Defined when using Tcl8.0 SWIGPERL Defined when using Perl SWIGPERL4 Defined when using Perl4 SWIGPERL5 Defined when using Perl5 SWIGPYTHON Defined when using Python SWIGGUILE Defined when using Guile SWIGWIN Defined when running SWIG under Windows SWIGMAC Defined when running SWIG on the Macintosh
The headers portion typically contains header files, supporting code, helper functions, and forward declarations. If you look at it, you'll usually find a hideous mess since this also contains the SWIG run-time pointer type-checker and internal functions used by the wrapper functions. The "wrapper" portion of the output contains all of the wrapper functions. Finally, the initialization function is a single C function that is created to initialize your module when it is loaded.
%module mymodule %{ #include "my_header.h" %} ... Declare functions here %{ ... Include Tcl_AppInit() function here ... %}
Code blocks are also typically used to write "helper" functions. These are functions that are used specifically for the purpose of building an interface and are generally not visible to the normal C program. For example :
%{ /* Create a new vector */ static Vector *new_Vector() { return (Vector *) malloc(sizeof(Vector)); } %} // Now wrap it Vector *new_Vector();
The %inline directive inserts all of the code that follows verbatim into the header portion of an interface file. The code is then fed into the SWIG parser and turned into an interface. Thus, the above example creates a new command new_Vector using only one declaration. Since the code inside an %inline %{ ... %} block is given to both the C compiler and SWIG, it is illegal to include any SWIG directives inside the %{ ... %} block.%inline %{ /* Create a new vector */ Vector *new_Vector() { return (Vector *) malloc(sizeof(Vector)); } %}
%init %{ init_variables(); %}
This code is inserted directly into SWIG's initialization function. You can use it to perform additional initialization and operations. Since this code is inserted directly into another function, it should not declare functions or include header files. Primarily this can be used to add callouts to widgets and other packages that might also need to be initialized when your extension is loaded.
This directive, for almost all practical purposes, is identical to just using a %{,%} block, but may be required for more sophisticated applications. It is mainly only used for advanced features in the SWIG library. As a general rule, you should avoid using this directive unless you absolutely know what you are doing.%wrapper %{ ... a bunch of code ... %}
While this may sound complicated, the process turns out to be relatively easy in practice--for example, making an interface to the entire OpenGL library only takes about 5-10 minutes.
In the process of building an interface, you are encouraged to use SWIG to find problematic declarations and specifications. SWIG will report syntax errors and other problems along with the associated file and line number.
A typical SWIG interface file for this header file would look like the following :/* File : header.h */ #include <stdio.h> #include <math.h> extern int foo(double); extern double bar(int, int); extern void dump(FILE *f);
Of course, in this case, our header file is pretty simple so we could have made an interface file like this as well:/* File : interface.i */ %module mymodule %{ #include "header.h" %} extern int foo(double); extern double bar(int, int); extern void dump(FILE *f);
/* File : interface.i */ %module mymodule %include header.h
Naturally, your mileage may vary.
%module graphics %{ #include <GL/gl.h> #include <GL/glu.h> %} // Put rest of declarations here ...
Getting rid of main() may cause potential initialization problems of a program. To handle this problem, you may consider writing a special function called program_init() that initializes your program upon startup. This function could then be called either from the scripting language as the first operation, or when the SWIG generated module is loaded.
As a general note, many C programs only use the main() function to parse command line options and to set parameters. However, by using a scripting language, you are probably trying to create a program that is more interactive. In many cases, the old main() program can be completely replaced by a Perl, Python, or Tcl script.
Writing a nice interface to a package requires work. Just because you use SWIG it doesn't mean that you're going to end up with a good interface. SWIG is primarily designed to eliminate the tedious task of writing wrapper functions. It does not eliminate the need for proper planning and design when it comes to building a useful application. In short, a little forethought can go a long way.
Of course,if you're primarily interested in just slapping something together for the purpose of debugging, rapid application development, and prototyping, SWIG will gladly do it for you (in fact, I use SWIG alot for this when developing other C/C++ applications).