SWIG Internals Manual

Thien-Thi Nguyen
ttn@glug.org
(with much help from others)

$Header$

(Note : This is a work in progress.)

1. Introduction

This document details SWIG internals: architecture and sometimes implementation. The first few sections concentrate on data structures, interfaces, conventions and code shared by all language targets. Subsequent sections focus on a particular language.

The audience is assumed to be SWIG developers (who should also read the SWIG Engineering Manual before starting to code).

Directory Guide

Doc HTML documentation. If you find a documentation bug, please let us know.
Examples This subdir tree contains examples of using SWIG w/ different scripting languages, including makefiles. Typically, there are the "simple" and "matrix" examples, w/ some languages offering additional examples. The GIFPlot example has its own set of per-language subdirectories. See the README more index.html file in each directory for more info. [FIXME: Ref SWIG user manual.]
Lib These are the .i (interface) files that form the SWIG installed library. Language-specific files are in subdirectories (for example, guile/typemaps.i). Each language also has a .swg file implementing runtime type support for that language. The SWIG library is not versioned.
Misc Currently this subdir only contains file fileheader. See the Engineering Manual for more info.
Runtime This subdir contains scripts and a makefile for creating runtime shared-object libraries used by various languages. Runtime/make.sh says: "The runtime libraries are only needed if you are building multiple extension modules that need to share information."
Source SWIG source code is in this subdir tree. Directories marked w/ "(*)" are used in building the swig executable.
DOH (*) C library providing memory allocation, file access and generic containers. Result: libdoh.a
Expat [TODO]
Experiment [TODO]
Include (*) Configuration .h files
LParse Parser (lex / yacc) files and support [why not (*)?!]
Modules [TODO]
Modules1.1 (*) Language-specific callbacks that does actual code generation (each language has a .cxx and a .h file). Result: libmodules11.a
Preprocessor (*) SWIG-specialized C/C++ preprocessor. Result: libcpp.a
SWIG1.1 (*) Parts of SWIG that are not language-specific, including option processing and the type-mapping system. Result: libswig11.a
SWIG1.3 [TODO] [funny, nothing here is presently used for swig-1.3]
SWILL [TODO]
Swig (*) [TODO]
Swim [TODO]
Swithe [TODO]
Xmlparse [TODO]
Tools Libtool support and the mkdist.py script.
Win This improperly-named (spit spit) subdir only has README.txt.

Overall Program Flow

Here is the general control flow and where under subdir Source to look for code:

Table of Contents

2. DOH

[TODO]

3. Types and Typemaps

[TODO]

4. Parsing

[TODO]

5. Difference Between SWIG 1.1 and SWIG 1.3

[TODO]

6. Plans for SWIG 2.0

[TODO]

7. Reserved

8. Reserved

9. Reserved

10. Guile Support

This section details guile-specific support in SWIG.

Meaning of "Module"

There are three different concepts of "module" involved, defined separately for SWIG, Guile, and Libtool. To avoid horrible confusion, we explicitly prefix the context, e.g., "guile-module".

Linkage

Guile support is complicated by a lack of user community cohesiveness, which manifests in multiple shared-library usage conventions. A set of policies implementing a usage convention is called a linkage. The default linkage is the simplest; nothing special is done. In this case SWIG_init() is provided and users must do something like this:

(define my-so (dynamic-link "./example.so"))
(dynamic-call "SWIG_init" my-so)
At this time, the name SWIG_init is hardcoded; this approach does not work with multiple swig-modules. NOTE: The "simple" and "matrix" examples under Examples/guile include guilemain.i; the resulting standalone interpreter does not require calls to dynamic-link and dynamic-call, as shown here.

A second linkage creates "libtool dl module" wrappers, and currently is broken. Whoever fixes this needs to track Guile's libtool dl module convention, since that is not finalized.

The only other linkage supported at this time creates shared object libraries suitable for use by hobbit's (hobbit4d link) guile module. This is called the "hobbit" linkage, and requires also using the "-package" command line option to set the part of the module name before the last symbol. For example, both command lines: [checkme:ttn]

swig -guile -package my/lib foo.i
swig -guile -package my/lib -module foo foo.i
would create module (my lib foo) (assuming in the first case foo.i declares the module to be "foo"). The installed files are my/lib/libfoo.so.X.Y.Z and friends. This scheme is still very experimental; the (hobbit4d link) conventions are not well understood.

There are no other linkage types planned, but that could change... To add a new type, add the name to the enum in guile.h and add the case to GUILE::emit_linkage().

Underscore Folding

Underscores are converted to dashes in identifiers. Guile support may grow an option to inhibit this folding in the future, but no one has complained so far.

Typemaps

It used to be that the mappings for "native" types were included in guile.cxx. This information is now in Lib/guile/typemaps.i, which presents a new challenge: how to have SWIG include typemaps.i before processing the user's foo.i. At this time, we must say:

%include guile/typemaps.i
in foo.i. This may change in the future.

Smobs

For pointer types, SWIG can use Guile smobs if given the command-line option "-with-smobs". Ultimately this will be the default (and only) behavior and the command-line option will no longer be supported. Ideally, "-with-smobs" will not even make it to beta.

Currently, one wrapper module must be generated without -c and compiled with -DSWIG_GLOBAL, all the other wrapper modules must be generated with -c. Maybe one should move all the global helper functions that come from guile.swg into a library, which is built by make runtime.

In earlier versions of SWIG, C pointers were represented as Scheme strings containing a hexadecimal rendering of the pointer value and a mangled type name. As Guile allows registering user types, so-called "smobs" (small objects), a much cleaner representation has been implemented now. The details will be discussed in the following.

A smob is a cons cell where the lower half of the CAR contains the smob type tag, while the upper half of the CAR and the whole CDR are available. SWIG_Guile_Init() registers a smob type named "swig" with Guile; its type tag is stored in the variable swig_tag. The upper half of the CAR store an index into a table of all C pointer types seen so far, to which new types seen are appended. The CDR stores the pointer value. SWIG smobs print like this: #<swig struct xyzzy * 0x1234affe> Two of them are equal? if and only if they have the same type and value.

To construct a Scheme object from a C pointer, the wrapper code calls the function SWIG_Guile_MakePtr_Str(), passing both a mangled type string and a pretty type string. The former is looked up in the type table to get the type index to store in the upper half of the CAR. If the type is new, it is appended to type table.

To get the pointer represented by a smob, the wrapper code calls the function SWIG_Guile_GetPtr_Str, passing the mangled name of the expected pointer type, which is used for looking up the type in the type table and accessing the list of compatible types. If the Scheme object passed was not a SWIG smob representing a compatible pointer, a wrong-type-arg exception is raised.

Exception Handling

SWIG code calls scm_error on exception, using the following mapping:

      MAP(SWIG_MemoryError,	"swig-memory-error");
      MAP(SWIG_IOError,		"swig-io-error");
      MAP(SWIG_RuntimeError,	"swig-runtime-error");
      MAP(SWIG_IndexError,	"swig-index-error");
      MAP(SWIG_TypeError,	"swig-type-error");
      MAP(SWIG_DivisionByZero,	"swig-division-by-zero");
      MAP(SWIG_OverflowError,	"swig-overflow-error");
      MAP(SWIG_SyntaxError,	"swig-syntax-error");
      MAP(SWIG_ValueError,	"swig-value-error");
      MAP(SWIG_SystemError,	"swig-system-error");

The default when not specified here is to use "swig-error". See Lib/exception.i for details.

10. Python Support

[TODO]

10. Perl Support

[TODO]

10. Java Support

[TODO]