8 SWIG and Perl5

Caution: This chapter is under repair! In this chapter, we discuss SWIG's support of Perl5. While the Perl5 module is one of the earliest SWIG modules, it has continued to evolve and has been improved greatly with the help of SWIG users. For the best results, it is recommended that SWIG be used with Perl5.003 or later. Earlier versions are problematic and SWIG generated extensions may not compile or run correctly.

Preliminaries

In order for this section to make much sense, you will need to have Perl5.002 (or later) installed on your system. You should also determine if your version of Perl has been configured to use dynamic loading or not. SWIG will work with or without it, but the compilation process will be different.

Running SWIG

To build a Perl5 module, run swig using the -perl5 option as follows :

swig -perl5 example.i

This will produce 3 files. The first file, example_wrap.c contains all of the C code needed to build a Perl5 module. The second file, example.pm contains supporting Perl code needed to properly load the module into Perl. The third file will be a documentation file (the exact filename depends on the documentation style). To finish building a module, you will need to compile the file example_wrap.c and link it with the rest of your program (and possibly Perl itself). There are several methods for doing this.

Getting the right header files

In order to compile, you will need to use the following Perl5 header files :

#include "Extern.h"
#include "perl.h"
#include "XSUB.h"

These are usually located in a directory like this

/usr/local/lib/perl5/arch-osname/5.003/CORE

The SWIG configuration script will try to find this directory, but it's not entirely foolproof. You may have to dig around yourself.

Compiling a dynamic module

To compile a dynamically loadable module, you will need to do something like the following,

% gcc example.c
% gcc example_wrap.c -I/usr/local/lib/perl5/arch-osname/5.003/CORE 
	-Dbool=char -c
% ld -shared example.o example_wrap.o -o example.so    # Irix

The name of the shared object file must match the module name used in the SWIG interface file. If you used `%module example', then the target should be named `example.so', `example.sl', or the appropriate name on your system (check the man pages for the linker).

Unfortunately, the process of building dynamic modules varies on every single machine. Both the C compiler and linker may need special command line options. SWIG tries to guess how to build dynamic modules on your machine in order to run its example programs. Again, the configure script isn't foolproof .

Building a dynamic module with MakeMaker

It is also possible to use Perl to build dynamically loadable modules for you using the MakeMaker utility. To do this, write a simple Perl script such as the following :

# File : Makefile.PL
use ExtUtils::MakeMaker;
WriteMakefile(
	`NAME'    => `example',                  # Name of package
	`LIBS'    => [`-lm'],                    # Name of custom libraries
	`OBJECT'  => `example.o example_wrap.o'  # Object files
);

Now, to build a module, simply follow these steps :

% perl Makefile.PL
% make
% make install

This is the preferred approach if you building general purpose Perl5 modules for distribution. More information about MakeMaker can be found in "Programming Perl, 2nd ed." by Larry Wall, Tom Christiansen, and Randal Schwartz.

Building a static version of Perl

If you machine does not support dynamic loading, or if you've tried to use it without success, you can build a new version of the Perl interpreter with your SWIG extensions added to it. To build a static extension, you first need to invoke SWIG as follows :

% swig -perl5 -static example.i

By default SWIG includes code for dynamic loading, but the -static option takes it out.

Next, you will need to supply a main() function that initializes your extension and starts the Perl interpreter. While, this may sound daunting, SWIG can do this for you automatically as follows :

%module example

extern double My_variable;
extern int fact(int);

// Include code for rebuilding Perl
%include perlmain.i

The same thing can be accomplished by running SWIG as follows :

% swig -perl5 -static -lperlmain.i example.i

The permain.i file inserts Perl's main() function into the wrapper code and automatically initializes the SWIG generated module. If you just want to make a quick a dirty module, this may be the easiest way. By default, the perlmain.i code does not initialize any other Perl extensions. If you need to use other packages, you will need to modify it appropriately. You can do this by just copying perlmain.i out of the SWIG library, placing it in your own directory, and modifying it to suit your purposes.

To build your new Perl executable, follow the exact same procedure as for a dynamic module, but change the link line as follows :

% ld example.o example_wrap.o -L/usr/local/lib/perl5/arch/5.003/CORE \
	-lperl -lsocket -lnsl -lm -o myperl

This will produce a new version of Perl called myperl. It should be functionality identical to Perl with your C/C++ extension added to it. Depending on your machine, you may need to link with additional libraries such as -lsocket, -lnsl, -ldl, etc...

Compilation problems and compiling with C++

In some cases, you may get alot of error messages about the `bool' datatype when compiling a SWIG module. If you experience this problem, you can try the following :

Compiling dynamic modules for C++ is also a tricky business. When compiling C++ modules, you may need to link using the C++ compiler such as :

unix > c++ -shared example_wrap.o example.o -o example.so

It may also be necessary to link against the libgcc.a, libg++.a, and libstdc++.a libraries (assuming g++). C++ may also complain about one line in the Perl header file "perl.h" and the invalid use of the "explicit" keyword. To work around this problem, put the option -Dexplicit= in your compiler flags.

If all else fails, put on your wizard cap and start looking around in the header files. Once you've figured out how to get one module to compile, you can compile just about all other modules.

Building Perl Extensions under Windows 95/NT

Building a SWIG extension to Perl under Windows 95/NT is roughly similar to the process used with Unix. Normally, you will want to produce a DLL that can be loaded into the Perl interpreter. This section assumes you are using SWIG with Microsoft Visual C++ 4.x although the procedure may be similar with other compilers. SWIG currently supports the ActiveWare Perl for Win32 port and Perl 5.004. If using the ActiveWare version, all Perl extensions must be compiled using C++!

Running SWIG from Developer Studio

If you are developing your application within Microsoft developer studio, SWIG can be invoked as a custom build option. The process roughly requires these steps :

Now, assuming all went well, SWIG will be automatically invoked when you build your project. Any changes made to the interface file will result in SWIG being automatically invoked to produce a new version of the wrapper file. To run your new Perl extension, simply run Perl and use the use command as normal. For example :

DOS > perl
use example;
$a = example::fact(4);
print "$a\n";

It appears that DLL's will work if they are placed in the current working directory. To make a generally DLL available, it should be place (along with its support files) in the Lib\Auto\[module] sub-directory of the Perl directory where [module] is the name of your module.

Using NMAKE

Alternatively, SWIG extensions can be built by writing a Makefile for NMAKE. To do this, make sure the environment variables for MSVC++ are available and the MSVC++ tools are in your path. Now, just write a short Makefile like this :

# Makefile for building an ActiveWare Perl for Win32 extension
# Note : Extensions must be compiled with the C++ compiler!

SRCS          = example.cxx
IFILE         = example
INTERFACE     = $(IFILE).i
WRAPFILE      = $(IFILE)_wrap.cxx

# Location of the Visual C++ tools (32 bit assumed)

TOOLS         = c:\msdev
TARGET        = example.dll
CC            = $(TOOLS)\bin\cl.exe
LINK          = $(TOOLS)\bin\link.exe
INCLUDE32     = -I$(TOOLS)\include
MACHINE       = IX86

# C Library needed to build a DLL

DLLIBC        = msvcrt.lib oldnames.lib  

# Windows libraries that are apparently needed
WINLIB        = kernel32.lib advapi32.lib user32.lib gdi32.lib comdlg32.lib 
winspool.lib

# Libraries common to all DLLs
LIBS          = $(DLLIBC) $(WINLIB) 

# Linker options
LOPT      = -debug:full -debugtype:cv /NODEFAULTLIB /RELEASE /NOLOGO /
MACHINE:$(MACHINE) -entry:_DllMainCRTStartup@12 -dll

# C compiler flags

CFLAGS        = /Z7 /Od /c /W3 /nologo

# Perl 5.004
PERL_INCLUDE = -Id:\perl5\lib\CORE
PERLLIB      = d:\perl5\lib\CORE\perl.lib
PERLFLAGS    = /DWIN32 /DMSWIN32 /DWIN32IO_IS_STDIO

# ActiveWare
PERL_INCLUDE  = -Id:\perl -Id:\perl\inc 
PERL_LIB        = d:\perl\Release\perl300.lib
PERLFLAGS = /DWIN32 /DMSWIN32 /DPERL_OBJECT

perl::
	..\..\swig -perl5 -o $(WRAPFILE) $(INTERFACE)
	$(CC) $(CFLAGS) $(PERLFLAGS) $(PERL_INCLUDE) $(SRCS) $(WRAPFILE)
	set LIB=$(TOOLS)\lib
	$(LINK) $(LOPT) -out:example.dll $(LIBS) $(PERLLIB) example.obj 
example_wrap.obj

To build the extension, run NMAKE (note that you may be to run vcvars32 before doing this to set the correct environment variables). This is a simplistic Makefile, but hopefully its enough to get you started.

Modules, packages, and classes

When you create a SWIG extension, everything gets thrown together into a single Perl5 module. The name of the module is determined by the %module directive. To use the module, do the following :

% perl5
use example;                      # load the example module
print example::fact(4),"\n"       # Call a function in it
24

Usually, a module consists of a collection of code that is contained within a single file. A package, on the other hand, is the Perl equivalent of a namespace. A package is alot like a module, except that it is independent of files. Any number of files may be part of the same package--or a package may be broken up into a collection of modules if you prefer to think about it in this way.

By default, SWIG installs its functions into a package with the same name as the module. This can be changed by giving SWIG the -package option :

% swig -perl5 -package FooBar example.i

In this case, we still create a module called `example', but all of the functions in that module will be installed into the package `FooBar.' For example :

use example;                       # Load the module like before
print FooBar::fact(4),"\n";        # Call a function in package FooBar

Perl supports object oriented programming using packages. A package can be thought of as a namespace for a class containing methods and data. The reader is well advised to consult "Programming Perl, 2nd Ed." by Wall, Christiansen, and Schwartz for most of the gory details.

Basic Perl interface

Functions

C functions are converted into new Perl commands (or subroutines). Default/optional arguments are also allowed. An interface file like this :

%module example
int foo(int a);
double bar (double, double b = 3.0);
...

Will be used in Perl like this :

use example;
$a = &example::foo(2);
$b = &example::bar(3.5,-1.5);
$c = &example::bar(3.5);            # Use default argument for 2nd parameter

Okay, this is pretty straightforward...enough said.

Global variables

Global variables are handled using pure magic--well, Perl's magic variable mechanism that is. In a nutshell, it is possible to make certain Perl variables "magical" by attaching methods for getting and setting values among other things. SWIG generates a pair of functions for accessing C global variables and attaches them to a Perl variable of the same name. Thus, an interface like this

%module example;
...
double Spam;
...

is accessed as follows :

use example;
print $example::Spam,"\n";
$example::Spam = $example::Spam + 4
# ... etc ...

SWIG supports global variables of all C datatypes including pointers and complex objects.

Constants

Constants are created as read-only magical variables and operate in exactly the same manner.

Pointers

SWIG represents pointers as blessed references. A blessed reference is the same as a Perl reference except that it has additional information attached to it indicating what kind of reference it is. That is, if you have a C declaration like this :

Matrix *new_Matrix(int n, int m);

SWIG will return a value as if you had done this :

$ptr = new_Matrix(int n, int m);     # Save pointer return result
bless $ptr, "MatrixPtr";             # Bless it as a MatrixPtr

SWIG uses the "blessing" to check the datatype of various pointers. In the event of a mismatch, an error or warning message will be generated.

To check to see if a value is the NULL pointer, use the defined() command :

if (defined($ptr)) {
	print "Not a NULL pointer.";
} else {
	print "Is a NULL pointer.";
}

To create a NULL pointer, you should pass the undef value to a function.

The "value" of a Perl reference is not the same as the underlying C pointer that SWIG wrapper functions return. Suppose that $a and $b are two references that point to the same C object. In general, $a and $b will be different--since they are different references. Thus, it is a mistake to check the equality of $a and $b to check the equality of two C pointers. The correct method to check equality of C pointers is to dereference them as follows :

if ($$a == $$b) {
	print "a and b point to the same thing in C";
} else {
	print "a and b point to different objects.";
}

It is easy to get burned by references in more subtle ways. For example, if you are storing a hash table of objects, it may be best to use the actual C pointer value rather than the Perl reference as a key. Since each Perl reference to the same C object may be different, it would be impossible to find anything in the hash without this. As a general rule, the best way to avoid problems with references is to make sure hash tables, comparisons, and other pointer operations use the value of the reference (ie. $$a), not the reference itself.

Structures and C++ classes

For structures and classes, SWIG produces a set of accessor functions for member functions and member data. For example :

%module vector

class Vector {
public:
	double x,y,z;
	Vector();
	~Vector();
	double magnitude();
};

This gets turned into the following collection of Perl functions :

vector::Vector_x_get($obj);
vector::Vector_x_set($obj,$x);
vector::Vector_y_get($obj);
vector::Vector_y_set($obj,$y);
vector::Vector_z_get($obj);
vector::Vector_z_set($obj,$z);
vector::new_Vector();
vector::delete_Vector($obj);
vector::Vector_magnitude($obj);

To use the class, simply use these functions. As it turns out, SWIG has a mechanism for creating shadow classes that hides these functions and uses an object oriented interface instead--keep reading.

Examples

Write me.

Exception handling

The SWIG %except directive can be used to create a user-definable exception handler for converting exceptions in your C/C++ program into Perl exceptions. The chapter on exception handling contains more details, but suppose you have a C++ class like the following :

class RangeError {};   // Used for an exception

class DoubleArray {
  private:
    int n;
    double *ptr;
  public:
    // Create a new array of fixed size
    DoubleArray(int size) {
      ptr = new double[size];
      n = size;
    }
    // Destroy an array
    ~DoubleArray() {
       delete ptr;
    }
    // Return the length of the array
    int   length() {
      return n;
    }

    // Get an item from the array and perform bounds checking.
    double getitem(int i) {
      if ((i >= 0) && (i < n))
        return ptr[i];
      else
        throw RangeError();
    }

    // Set an item in the array and perform bounds checking.
    void setitem(int i, double val) {
      if ((i >= 0) && (i < n))
        ptr[i] = val;
      else {
        throw RangeError();
      }
    }
  };

The functions associated with this class can throw a range exception for an out-of-bounds array access. We can catch this in our Perl extension by specifying the following in an interface file :

%except(perl5) {
  try {
    $function                // Gets substituted by actual function call
  }
  catch (RangeError) {
    croak("Array index out-of-bounds");
  }
}

Now, when the C++ class throws a RangeError exception, our wrapper functions will catch it, turn it into a Perl exception, and allow a graceful death as opposed to just having some sort of mysterious program crash. Since SWIG's exception handling is user-definable, we are not limited to C++ exception handling. It is also possible to write a language-independent exception handler that works with other scripting languages. Please see the chapter on exception handling for more details.

Remapping datatypes with typemaps

While SWIG does a reasonable job with most C/C++ datatypes, it doesn't always do what you want. However, you can remap SWIG's treatment of just about any datatype using a typemap. A typemap simply specifies a conversion between Perl and C datatypes and can be used to process function arguments, function return values, and more. A similiar mechanism is used by the xsubpp compiler provided with Perl although the SWIG version provides many more options.

A simple typemap example

The following example shows how a simple typemap can be written :

%module example

%typemap(perl5,in) int {
	$target = (int) SvIV($source);
	printf("Received an integer : %d\n", $target);
}
...
extern int fact(int n);

Typemap specifications require a language name, method name, datatype, and conversion code. For Perl5, "perl5" should be used as the language name. The "in" method refers to the input arguments of a function. The `int' datatype tells SWIG that we are remapping integers. The conversion code is used to convert from a Perl scalar value to the corresponding datatype. Within the support code, the variable $source contains the source data (a Perl object) and $target contains the destination of the conversion (a C local variable).

When this example is used in Perl5, it will operate as follows :

use example;
$n = example::fact(6);
print "$n\n";
...

Output :
Received an integer : 6
720

General discussion of typemaps can be found in the main SWIG users reference.

Perl5 typemaps

The following typemap methods are available to Perl5 modules

%typemap(perl5,in) Converts Perl5 object to input function arguments.

%typemap(perl5,out) Converts function return value to a Perl5 value.

%typemap(perl5,varin) Converts a Perl5 object to a global variable.

%typemap(perl5,varout) Converts a global variable to a Perl5 object.

%typemap(perl5,freearg) Cleans up a function argument after a function call

%typemap(perl5,argout) Output argument handling

%typemap(perl5,ret) Clean up return value from a function.

%typemap(memberin) Setting of C++ member data (all languages).

%typemap(memberout) Return of C++ member data (all languages).

%typemap(perl5,check) Check value of input parameter.

Typemap variables

The following variables may be used within the C code used in a typemap :

$source Source value of a conversion

$target Target of conversion (where result should be stored)

$type C datatype being remapped

$mangle Mangled version of datatype (for blessing objects)

$arg Function argument (when applicable).

Name based type conversion

Typemaps are based both on the datatype and an optional name attached to a datatype. For example :

%module foo

// This typemap will be applied to all char ** function arguments
%typemap(perl5,in) char ** { ... }

// This typemap is applied only to char ** arguments named `argv'
%typemap(perl5,in) char **argv { ... }

In this example, two typemaps are applied to the char ** datatype. However, the second typemap will only be applied to arguments named `argv'. A named typemap will always override an unnamed typemap.

Due to the name matching scheme, typemaps do not follow typedef declarations. For example :

%typemap(perl5,in) double {
	... get a double ...
}

double foo(double);              // Uses the double typemap above
typedef double Real;
Real bar(Real);                  // Does not use the typemap above (double != Real)

Is is odd behavior to be sure, but you can work around the problem using the %apply directive as follows :

%typemap(perl5,in) double {
	... get a double ...
}
double foo(double);              // Uses the double typemap above

typedef double Real;
%apply double { Real };          // Apply the double typemap to Reals.
Real bar(Real);                  // Uses the double typemap already defined.

Named typemaps are extremely useful for managing special cases. It is also possible to use named typemaps to process output arguments (ie. function arguments that have values returned in them).

Converting a Perl5 array to a char **

A common problem in many C programs is the processing of command line arguments, which are usually passed in an array of NULL terminated strings. The following SWIG interface file allows a Perl5 array reference to be used as a char ** datatype.

%module argv

// This tells SWIG to treat char ** as a special case
%typemap(perl5,in) char ** {
	AV *tempav;
	I32 len;
	int i;
	SV  **tv;
	if (!SvROK($source))
	    croak("$source is not a reference.");
        if (SvTYPE(SvRV($source)) != SVt_PVAV)
	    croak("$source is not an array.");
       tempav = (AV*)SvRV($source);
	len = av_len(tempav);
	$target = (char **) malloc((len+2)*sizeof(char *));
	for (i = 0; i <= len; i++) {
	    tv = av_fetch(tempav, i, 0);	
	    $target[i] = (char *) SvPV(*tv,na);
        }
	$target[i] = 0;
};

// This cleans up our char ** array after the function call
%typemap(perl5,freearg) char ** {
	free($source);
}

// Creates a new Perl array and places a char ** into it
%typemap(perl5,out) char ** {
	AV *myav;
	SV **svs;
	int i = 0,len = 0;
	/* Figure out how many elements we have */
	while ($source[len])
	   len++;
	svs = (SV **) malloc(len*sizeof(SV *));
	for (i = 0; i < len ; i++) {
	    svs[i] = sv_newmortal();
	    sv_setpv((SV*)svs[i],$source[i]);
	};
	myav =	av_make(len,svs);
	free(svs);
       $target = newRV((SV*)myav);
       sv_2mortal($target);
}

// Now a few test functions
%inline %{
int print_args(char **argv) {
    int i = 0;
    while (argv[i]) {
         printf("argv[%d] = %s\n", i,argv[i]);
         i++;
    }
    return i;
}

// Returns a char ** list 
char **get_args() {
    static char *values[] = { "Dave", "Mike", "Susan", "John", "Michelle", 0};
    return &values[0];
}
%}

When this module is compiled, our wrapped C functions can be used in a Perl script as follows :

use argv;
@a = ("Dave", "Mike", "John", "Mary");           # Create an array of strings
argv::print_args(\@a);                           # Pass it to our C function
$b = argv::get_args();                           # Get array of strings from C
print @$b,"\n";                                  # Print it out

Of course, there are many other possibilities. As an alternative to array references, we could pass in strings separated by some delimeter and perform a splitting operation in C.

Using typemaps to return values

Sometimes it is desirable for a function to return a value in one of its arguments. A named typemap can be used to handle this case. For example :

%module return

// This tells SWIG to treat an double * argument with name 'OutDouble' as
// an output value.  

%typemap(perl5,argout) double *OutDouble {
	$target = sv_newmortal();
	sv_setnv($target, *$source);
	argvi++;                     /* Increment return count -- important! */
}

// If we don't care what the input value is, we can make the typemap ignore it.

%typemap(perl5,ignore) double *OutDouble(double junk) {
	$target = &junk;       /* junk is a local variable that has been declared */
}

// Now a function to test it
%{
/* Returns the first two input arguments */
int multout(double a, double b, double *out1, double *out2) {
	*out1 = a;
	*out2 = b;
	return 0;
};
%}

// If we name both parameters OutDouble both will be output

int multout(double a, double b, double *OutDouble, double *OutDouble);
...

When output arguments are encountered, they are simply appended to the stack used to return results. This will show up as an array when used in Perl. For example :

@r = multout(7,13);
print "multout(7,13) = @r\n";

Accessing array structure members

Consider the following data structure :

#define NAMELEN   32
typedef struct {
	char   name[NAMELEN];
	...
} Person;

By default, SWIG doesn't know how to the handle the name structure since it's an array, not a pointer. In this case, SWIG will make the array member readonly. However, member typemaps can be used to make this member writable from Perl as follows :

%typemap(memberin) char[NAMELEN] {
	/* Copy at most NAMELEN characters into $target */
	strncpy($target,$source,NAMELEN);
}

Whenever a char[NAMELEN] type is encountered in a structure or class, this typemap provides a safe mechanism for setting its value. An alternative implementation might choose to print an error message if the name was too long to fit into the field.

It should be noted that the [NAMELEN] array size is attached to the typemap. A datatype involving some other kind of array would be affected. However, we can write a typemap that will work for any array dimension as follows :

%typemap(memberin) char [ANY] {
	strncpy($target,$source,$dim0);
}

When code is generated, $dim0 gets filled in with the real array dimension.

Turning Perl references into C pointers

A frequent confusion on the SWIG mailing list is errors caused by the mixing of Perl references and C pointers. For example, suppose you have a C function that modifies its arguments like this :

void add(double a, double b, double *c) {
	*c = a + b;
}

A common misinterpretation of this function is the following Perl script :

# Perl script
$a = 3.5;
$b = 7.5;
$c = 0.0;          # Output value
add($a,$b,\$c);    # Place result in c (Except that it doesn't work)

Unfortunately, this does NOT work. There are many reasons for this, but the main one is that SWIG has no idea what a double * really is. It could be an input value, an output value, or an array of 2 million elements. As a result, SWIG leaves it alone and looks exclusively for a C pointer value (which is not the same as a Perl reference--well, at least note of the type used in the above script).

However, you can use a typemap to get the desired effect. For example :

%typemap(perl5,in) double * (double dvalue) {
  SV* tempsv;
  if (!SvROK($source)) {
    croak("expected a reference\n");
  }
  tempsv = SvRV($source);
  if ((!SvNOK(tempsv)) && (!SvIOK(tempsv))) {
    croak("expected a double reference\n");
  }
  dvalue = SvNV(tempsv);
  $target = &dvalue;
}

%typemap(perl5,argout) double * {
  SV *tempsv;
  tempsv = SvRV($arg);
  sv_setnv(tempsv, *$source);
}

Now, if you place this before our add function, we can do this :

$a = 3.5;
$b = 7.5;
$c = 0.0;
add($a,$b,\$c);            # Now it works!
print "$c\n";

You'll get the output value of "11.0" which is exactly what we wanted. While this is pretty cool, it should be stressed that you can easily shoot yourself in the foot with typemaps--of course SWIG is has never been too concerned about legislating morality....

Useful functions

When writing typemaps, it is necessary to work directly with Perl5 objects. This, unfortunately, can be a daunting task. Consult the "perlguts" man-page for all of the really ugly details. A short summary of commonly used functions is provided here for reference. It should be stressed that SWIG can be usef quite effectively without knowing any of these details--especially now that there are typemap libraries that can already been written.

Perl Integer Functions

int   SvIV(SV *);
void  sv_setiv(SV *sv, IV value);
SV   *newSViv(IV value);
int   SvIOK(SV *);
Perl Floating Point Functions
double SvNV(SV *);
void   sv_setnv(SV *, double value);
SV    *newSVnv(double value);
int    SvNOK(SV *);
Perl String Functions
char     *SvPV(SV *, int len);
void      sv_setpv(SV *, char *val);
void      sv_setpvn(SV *, char *val, int len);
SV       *newSVpv(char *value, int len);
int       SvPOK(SV *);
void      sv_catpv(SV *, char *);
void      sv_catpvn(SV *, char *, int);
Perl References
void      sv_setref_pv(SV *, char *, void *ptr);
int       sv_isobject(SV *);
SV       *SvRV(SV *);
int       sv_isa(SV *, char *0;

Standard typemaps

The following typemaps show how to convert a few common types of objects between Perl and C (and to give a better idea of how everything works).

(rewrite)

Pointer handling

SWIG pointers are represented as blessed references. The following functions can be used to create and read pointer values.

(rewrite)

Return values

Return values are placed on the argument stack of each wrapper function. The current value of the argument stack pointer is contained in a variable argvi. Whenever a new output value is added, it is critical that this value be incremented. For multiple output values, the final value of argvi should be the total number of output values.

The total number of return values should not exceed the number of input values unless you explicitly extend the argument stack. This can be done using the EXTEND() macro as in :

%typemap(perl5,argout) int *OUTPUT {
	if (argvi >= items) {            
		EXTEND(sp,1);              /* Extend the stack by 1 object */
	}
	$target = sv_newmortal();
	sv_setiv($target,(IV) *($source));
	argvi++;
}

The gory details on shadow classes

Perl5 shadow classes are constructed on top of the low-level C interface provided by SWIG. By implementing the classes in Perl instead of C, we get a number of advantages :

Shadow classes are new in SWIG 1.1 and still somewhat experimental. The current implementation is a combination of contributions provided by Gary Holt and David Fletcher--many thanks!

Module and package names

When shadow classing is enabled, SWIG generates a low-level package named `modulec' where `module' is the name of the module you provided with the %module directive (SWIG appends a `c' to the name to indicate that it is the low-level C bindings). This low-level package is exactly the same module that SWIG would have created without the `-shadow' option, only renamed.

Using the low-level interface, SWIG creates Perl wrappers around classes, structs, and functions. This collection of wrappers becomes the Perl module that you will use in your Perl code, not the low-level package (the original package is hidden, but working behind the scenes).

What gets created?

Suppose you have the following SWIG interface file :

%module vector
struct Vector {
	Vector(double x, double y, double z);
	~Vector();
	double x,y,z;
};

When wrapped, SWIG creates the following set of low-level accessor functions.

Vector *new_Vector(double x, double y, double z);
void    delete_Vector(Vector *v);
double  Vector_x_get(Vector *v);
double  Vector_x_set(Vector *v, double value);
double  Vector_y_get(Vector *v);
double  Vector_y_set(Vector *v, double value);
double  Vector_z_get(Vector *v);
double  Vector_z_set(Vector *v, double value);

These functions can now be used to create a Perl shadow class that looks like this :

package Vector;
@ISA = qw( vector );
%OWNER = ();
%BLESSEDMEMBERS = ();

sub new () {
    my $self = shift;
    my @args = @_;
    $self = vectorc::new_Vector(@args);
    return undef if (!defined($self));
    bless $self, "Vector";
    $OWNER{$self} = 1;
    my %retval;
    tie %retval, "Vector", $self;
    return bless \%retval,"Vector";
}

sub DESTROY {
    my $self = shift; 
    if (exists $OWNER{$self}) {
	 delete_Vector($self));
	 delete $OWNER{$self};
}

sub FETCH {
    my ($self,$field) = @_;
    my $member_func = "vectorc::Vector_${field}_get";
    my $val = &$member_func($self);
    if (exists $BLESSEDMEMBERS{$field}) {
        return undef if (!defined($val));
        my %retval;
        tie %retval,$BLESSEDMEMBERS{$field},$val;
        return bless \%retval, $BLESSEDMEMBERS{$field};
    }
    return $val;
}

sub STORE {
    my ($self,$field,$newval) = @_;
    my $member_func = "vectorc::Vector_${field}_set";
    if (exists $BLESSEDMEMBERS{$field}) {
        &$member_func($self,tied(%{$newval}));
    } else {
        &$member_func($self,$newval);
    }
}

Each structure or class is mapped into a Perl package of the same name. The C++ constructors and destructors are mapped into constructors and destructors for the package and are always named "new" and "DESTROY". The constructor always returns a tied hash table. This hash table is used to access the member variables of a structure in addition to being able to invoke member functions. The %OWNER and %BLESSEDMEMBERS hash tables are used internally and described shortly.

To use our new shadow class we can simply do the following:

# Perl code using Vector class
$v = new Vector(2,3,4);
$w = Vector->new(-1,-2,-3);

# Assignment of a single member
$v->{x} = 7.5;

# Assignment of all members
%$v = ( x=>3,
	 y=>9,
	 z=>-2);

# Reading members
$x = $v->{x};

# Destruction
$v->DESTROY();

Object Ownership

In order for shadow classes to work properly, it is necessary for Perl to manage some mechanism of object ownership. Here's the crux of the problem---suppose you had a function like this :

Vector *Vector_get(Vector *v, int index) {
	return &v[i];
}

This function takes a Vector pointer and returns a pointer to another Vector. Such a function might be used to manage arrays or lists of vectors (in C). Now contrast this function with the constructor for a Vector object :

Vector *new_Vector(double x, double y, double z) {
	Vector *v;
	v = new Vector(x,y,z);        // Call C++ constructor
	return v;
}

Both functions return a Vector, but the constructor is returning a brand-new Vector while the other function is returning a Vector that was already created (hopefully). In Perl, both vectors will be indistinguishable---clearly a problem considering that we would probably like the newly created Vector to be destroyed when we are done with it.

To manage these problems, each class contains two methods that access an internal hash table called %OWNER. This hash keeps a list of all of the objects that Perl knows that it has created. This happens in two cases: (1) when the constructor has been called, and (2) when a function implicitly creates a new object (as is done when SWIG needs to return a complex datatype by value). When the destructor is invoked, the Perl shadow class module checks the %OWNER hash to see if Perl created the object. If so, the C/C++ destructor is invoked. If not, we simply destroy the Perl object and leave the underlying C object alone (under the assumption that someone else must have created it).

This scheme works remarkably well in practice but it isn't foolproof. In fact, it will fail if you create a new C object in Perl, pass it on to a C function that remembers the object, and then destroy the corresponding Perl object (this situation turns out to come up frequently when constructing objects like linked lists and trees). When C takes possession of an object, you can change Perl's owership by simply deleting the object from the %OWNER hash. This is done using the DISOWN method.

# Perl code to change ownership of an object
$v = new Vector(x,y,z);
$v->DISOWN();     

To acquire ownership of an object, the ACQUIRE method can be used.

# Given Perl ownership of a file
$u = Vector_get($v);
$u->ACQUIRE();

As always, a little care is in order. SWIG does not provide reference counting, garbage collection, or advanced features one might find in sophisticated languages.

Nested Objects

Suppose that we have a new object that looks like this :

struct Particle {
	Vector r;
	Vector v;
	Vector f;
	int	type;
}

In this case, the members of the structure are complex objects that have already been encapsulated in a Perl shadow class. To handle these correctly, we use the %BLESSEDMEMBERS hash which would look like this (along with some supporting code) :

package Particle;
...
%BLESSEDMEMBERS = (
	r => `Vector',
	v => `Vector',
	f => `Vector',
);

When fetching members from the structure, %BLESSEDMEMBERS is checked. If the requested field is present, we create a tied-hash table and return it. If not, we just return the corresponding member unmodified.

This implementation allows us to operate on nested structures as follows :

# Perl access of nested structure
$p = new Particle();
$p->{f}->{x} = 0.0;
%${$p->{v}} = ( x=>0, y=>0, z=>0);         

Shadow Functions

When functions take arguments involving a complex object, it is sometimes necessary to write a shadow function. For example :

double dot_product(Vector *v1, Vector *v2);

Since Vector is an object already wrapped into a shadow class, we need to modify this function to accept arguments that are given in the form of tied hash tables. This is done by creating a Perl function like this :

sub dot_product {
    my @args = @_;
    $args[0] = tied(%{$args[0]});         # Get the real pointer values
    $args[1] = tied(%{$args[1]});
    my $result = vectorc::dot_product(@args);
    return $result;
}

This function replaces the original function, but operates in an identical manner.

Inheritance

Simple C++ inheritance is handled using the Perl @ISA array in each class package. For example, if you have the following interface file :

// shapes.i
// SWIG interface file for shapes class
%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();
}

The resulting, Perl wrapper class will create the following code :

Package Shape;
@ISA = (shapes);
...
Package Circle;
@ISA = (shapes Shape);
...
Package Square;
@ISA = (shapes Shape);

The @ISA array determines where to look for methods of a particular class. In this case, both the Circle and Square classes inherit functions from Shape so we'll want to look in the Shape base class for them. All classes also inherit from the top-level module shapes. This is because certain common operations needed to implement shadow classes are implemented only once and reused in the wrapper code for various classes and structures.

Since SWIG shadow classes are implemented in Perl, it is easy to subclass from any SWIG generated class. To do this, simply put the name of a SWIG class in the @ISA array for your new class. However, be forewarned that this is not a trivial problem. In particular, inheritance of data members is extremely tricky (and I'm not even sure if it really works).

Iterators

With each class or structure, SWIG also generates a pair of functions to support Perl iterators. This makes it possible to use the keys and each functions on a C/C++ object. Iterators are implemented using code like this :

sub FIRSTKEY {
    my $self = shift;
    @ITERATORS{$self} = [`x','y','z', ];
    my $first = shift @{$ITERATORS{$self}};
    return $first;
}

sub NEXTKEY {
    my $self = shift;
    $nelem = scalar @{$ITERATORS{$self}};
    if ($nelem > 0) {
        my $member = shift @{$ITERATORS{$self}};
        return $member;
    } else {
        @ITERATORS{$self} = [`x','y','z', ];
        return ();
    }
}
The %ITERATORS hash table maintains the state of each object for which the keys or each function has been applied to. The state is maintained by keeping a list of the member names.

While iterators may be of limited use when working with C/C++ code, it turns out they can be used to perform an element by element copy of an object.

$v = new Vector(1,2,3);
$w = new Vector(0,0,0);
%$w = %$v;                # Copy contents of v into w

However, this is not a deep copy so they probably works better with C than with C++.

Where to go from here?

The SWIG Perl5 module is constantly improving to provide better integration with Perl and to be easier to use. The introduction of shadow classes and typemaps in this release are one more step in that direction. The SWIG Examples directory contains more simple examples of building Perl5 modules. As always, suggestions for improving the Perl5 implementation are welcome.


SWIG 1.1 - Last Modified : Mon Aug 4 10:47:01 1997