David M. Beazley
beazley@cs.uchicago.edu
$Header$
(Note : This is a work in progress.)
The audience is assumed to be SWIG developers (who should also read the SWIG Engineering Manual before starting to code).
| 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.
|
||||||||||||||||||||
| Tools | Libtool support and the mkdist.py script. | ||||||||||||||||||||
| Win | This improperly-named (spit spit) subdir only has README.txt. |
DOH takes a different approach to tackling the complexity problem. First, rather than going overboard with dozens of types and class definitions, DOH only defines a handful of simple yet very useful objects that are easy to remember. Second, DOH uses dynamic typing---one of the features that make scripting languages so useful and which make it possible to accomplish things with much less code. Finally, DOH utilizes a few coding tricks that allow it to perform a limited form of function overloading for certain C datatypes (more on that a little later).
The key point to using DOH is that instead of thinking about code in terms of highly specialized C data structures, just about everything ends up being represented in terms of a just a few datatypes. For example, structures are replaced by DOH hash tables whereas arrays are replaced by DOH lists. At first, this is probably a little strange to most C/C++ programmers, but in the long run in makes the system extremely flexible and highly extensible. Also, in terms of coding, many of the newly DOH-based subsystems are less than half the size (in lines of code) of the earlier C++ implementation.
DOH *a, *b, *c, *d;
a = NewString("Hello World");
b = NewList();
c = Copy(a); /* Copy the string a */
d = Copy(b); /* Copy the list b */
Copies of lists and hash tables are shallow. That is, their contents are only copied by reference.
Objects can be deleted using the Delete() function. For example:
DOH *a = NewString("Hello World");
...
Delete(a); /* Destroy a */
All objects are referenced counted and given a reference count of 1 when initially created. The
Delete() function only destroys an object when the reference count reaches zero. When
an object is placed in a list or hash table, it's reference count is automatically increased. For example:
DOH *a, *b;
a = NewString("Hello World");
b = NewList();
Append(b,a); /* Increases refcnt of a to 2 */
Delete(a); /* Decreases refcnt of a to 1 */
Delete(b); /* Destroys b, and destroys a */
Should it ever be necessary to manually increase the reference count of an object, the DohIncref() function
can be used:
DOH *a = NewString("Hello");
DohIncref(a);
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".
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:
At this time, the name(define my-so (dynamic-link "./example.so")) (dynamic-call "SWIG_init" my-so)
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]
would create moduleswig -guile -package my/lib foo.i swig -guile -package my/lib -module foo foo.i
(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().
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.
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:
in foo.i. This may change in the future.%include guile/typemaps.i
For pointer types, SWIG uses Guile smobs. This feature used to be available only SWIG was invoked with the command-line option "-with-smobs", but as of 2000/07/06 (swig-1.3a4) this is the default behavior; the command-line option "-with-smobs" is ignored silently. We plan to drop silent recognition of this option after 1.3a4.
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.
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]