git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@411 626c5289-ae23-0410-ae9c-e8d60b6d4f22
575 lines
19 KiB
HTML
575 lines
19 KiB
HTML
<html>
|
|
<head>
|
|
<title>SWIG Engineering Manual</title>
|
|
</head>
|
|
<body bgcolor="#ffffff">
|
|
<center>
|
|
<h1>SWIG Engineering Manual</h1>
|
|
|
|
<b>David Beazley <br>
|
|
Department of Computer Science <br>
|
|
University of Chicago <br>
|
|
Chicago, IL 60637 <br>
|
|
beazley@cs.uchicago.edu <br>
|
|
</b>
|
|
</center>
|
|
|
|
<p>
|
|
<b>$Header$</b>
|
|
|
|
<p>
|
|
(Note : This is a work in progress.)
|
|
|
|
<h2>1. Introduction</h2>
|
|
|
|
The purpose of this document is to describe various coding conventions
|
|
and organizational aspects for SWIG developers. The idea for this
|
|
document is largely borrowed from John Ousterhout's Tcl/Tk Engineering
|
|
Manual. It is not my intent to overly managerial about matters--rather I'm
|
|
hoping to make life a little less chaotic for everyone.
|
|
|
|
<p>
|
|
First a little background: SWIG was started in 1995 as a one-person
|
|
project and continued in this mode of operation until about 1998.
|
|
Most of this development was driven by ideas submitted by early SWIG
|
|
users as opposed to being motivated by a grand design. As a result,
|
|
the code ended up being a pretty horrible C++ coding disaster. A
|
|
mostly working disaster perhaps, but a disaster nonetheless.
|
|
|
|
<p>
|
|
With that said, the primary goal of future SWIG development is to
|
|
reengineer the original system, fix most of its inherent design flaws,
|
|
and to produce what I hope will become a highly extensible and modular
|
|
interface compiler framework. To this do this, there are a few
|
|
critical areas of work. First, I want to restructure SWIG as a
|
|
collection of loosely coupled modules written in either ANSI C or an
|
|
scripting language. Second, I want the system to be minimalistic in
|
|
its use of data structures and interconnections. The primary reason
|
|
for this is that the fewer data structures there are, the less users
|
|
will have to remember. This will also make the system more accessible
|
|
to non-experts. Finally, I want to reevaluate the whole idea of a
|
|
SWIG module is and expand the definition to include just about
|
|
anything from parsers, preprocessors, optimizers, interface editors,
|
|
and code generators.
|
|
|
|
<p>
|
|
The rest of this document outlines a few general rules of how code
|
|
should be developed within the SWIG project. These rules are
|
|
primarily drawn from my own experience developing software and
|
|
observing the practices of other successful projects.
|
|
|
|
<h2>2. Programming Languages and Libraries </h2>
|
|
|
|
All SWIG modules must be written in either ANSI C or one of the
|
|
scripting languages for which SWIG can generate an interface (e.g.,
|
|
Perl, Python, or Tcl). <B>C++ is NOT an acceptable alternative and
|
|
will not be utilized for any future development due to the fact that
|
|
it is too complicated, too dogmatic, too problematic, and that Dave
|
|
would rather take a bullet to the head than write one more line of
|
|
code in this most decidedly unpleasant language. </B> Rare exceptions
|
|
to this rule may be made if there is a justifiable need to interface
|
|
an existing piece of software written in C++ into the SWIG module
|
|
system. Anyone who finds this rule to be unreasonable is more than
|
|
welcome to go write their own wrapper generator--so there.
|
|
|
|
<p>
|
|
Module writers should make every attempt to use only those functions
|
|
described in the POSIX.1 standard. This includes most of the
|
|
functions contained the Kernighan and Ritchie C programming book. Use
|
|
of operating system dependent functionality such as socket libraries
|
|
should always be included inside a conditional compilation block so
|
|
that it can be omitted on problematic platforms. If you are unsure
|
|
about a library call, check the man page or contact Dave.
|
|
|
|
<h2>3. The Source Directory and Module Names</h2>
|
|
|
|
All SWIG modules are contained within the "Source" directory. Within
|
|
this directory, each module is placed into its own subdirectory. The
|
|
name of this subdirectory should exactly match the name of the module.
|
|
For example, if you are creating a module called "Tcl", all of your
|
|
files should be placed in a directory "Tcl".
|
|
|
|
<p>
|
|
When choosing a module name, please pick a name that is not
|
|
currently in use. As a general convention, the first letter of a
|
|
module name is capitalized such as "Perl". Alternatives such as
|
|
"perl" or "PERL" should be avoided. In certain instances, the first
|
|
two letters may be capitalized as in "CParse." The exact usage of
|
|
this is somewhat inconsistent and isn't terribly important--just make
|
|
sure the first letter is capitalized. Also, module names should not
|
|
start with numbers, include underscores or any other special
|
|
non-alphanumeric characters.
|
|
|
|
<h2>4. Include files </h2>
|
|
|
|
All modules should include a header file that defines the public interface.
|
|
The name of this header file should be of the form "swigmodule.h" where
|
|
"module" is the name of your module. For example, if you created a
|
|
module "Perl", the header file should be named "swigperl.h". This scheme
|
|
should prevent header-file naming conflicts both within SWIG and when linking
|
|
parts of SWIG to the outside world.
|
|
|
|
<p>
|
|
All header files should include a short description, author information, copyright message,
|
|
CVS version, include guards, and be C++ aware. For example:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
/* -------------------------------------------------------------------------
|
|
* swigperl.h
|
|
*
|
|
* All of the externally visible functions in the Perl module.
|
|
*
|
|
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
|
*
|
|
* Copyright (C) 1999-2000, The University of Chicago.
|
|
* See the file LICENSE for information on usage and redistribution.
|
|
*
|
|
* $Header$
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
#ifndef _SWIGPERL_H
|
|
#define _SWIGPERL_H 1
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* Your declarations here */
|
|
...
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* _SWIGPERL_H */
|
|
</pre>
|
|
</blockquote>
|
|
|
|
|
|
<p>
|
|
To minimize compilation time, please include as few other header files as possible.
|
|
|
|
<h2>5. File Structure </h2>
|
|
|
|
Each file in a module should be given a filename that is all lowercase letters
|
|
such as "parser.c", not "Parser.c" or "PARSER.c". Please note that filenames
|
|
are case-insensitive on Windows so this convention will prevent you from inadvertantly
|
|
creating two files that differ in case-only.
|
|
|
|
<p>
|
|
Each file should include a short abstract, author information, copyright information, and
|
|
a CVS revision tag like this:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
/* -----------------------------------------------------------------------------
|
|
* include.c
|
|
*
|
|
* This file implements the functions used to locate and include files in
|
|
* the SWIG library. Functions for maintaining the library search path are
|
|
* also located here.
|
|
*
|
|
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
|
*
|
|
* Copyright (C) 1999-2000, The University of Chicago.
|
|
* See the file LICENSE for information on usage and redistribution.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static char cvsroot[] = "$Header$";
|
|
|
|
#include "swig.h"
|
|
|
|
/* Declarations */
|
|
typedef struct {
|
|
int x, y;
|
|
} Foo;
|
|
|
|
...
|
|
|
|
/* Private Declarations (used only in this file) */
|
|
static int avariable;
|
|
|
|
...
|
|
|
|
/* Functions */
|
|
...
|
|
|
|
</pre>
|
|
</blockquote>
|
|
|
|
The CVS revision tag should be placed into a static string as shown
|
|
above. This adds the revision information to the SWIG executable and
|
|
makes it possible to extract version information from a raw binary
|
|
(sometimes useful in debugging).
|
|
|
|
<p>
|
|
As a general rule, files start to get unmanagable once they exceed
|
|
about 2000 lines. Files larger than this should be broken up into
|
|
multiple files. Similarly, you should avoid the temptation to create
|
|
many small files as this increases compilation time and makes the
|
|
directory structure too complicated.
|
|
|
|
<h2>6. Bottom-Up Design </h2>
|
|
|
|
Within each source file, the preferred organization is to use what is
|
|
known as "bottom-up" design. Under this scheme, lower-level functions
|
|
appear first and the highest level function appears last. The easy
|
|
way to remember is that the "main" function of your module should
|
|
always appear last in the source file. For example:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
/* Simple bottom-up program */
|
|
#include <stdio.h>
|
|
|
|
int foo(int x, int y) {
|
|
/* Implement foo */
|
|
...
|
|
}
|
|
|
|
int bar() {
|
|
...
|
|
foo(i,j);
|
|
...
|
|
}
|
|
|
|
...
|
|
int main(int argc, char **argv) {
|
|
...
|
|
bar();
|
|
...
|
|
}
|
|
</pre>
|
|
</blockquote>
|
|
|
|
This choice of design is somewhat arbitrary however it has a number of
|
|
benefits particular to C. In particular, a bottom-up design generally
|
|
eliminates the need to include forward references--resulting in
|
|
cleaner code and fewer compilation errors.
|
|
|
|
<h2>7. Functions</h2>
|
|
|
|
All functions should have a function header that gives the function name
|
|
and a short description like this:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
/* -------------------------------------------------------------------------
|
|
* Swig_add_directory()
|
|
*
|
|
* Adds a directory to the SWIG search path.
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
void
|
|
Swig_add_directory(DOH *dirname) {
|
|
...
|
|
|
|
}
|
|
</pre>
|
|
</blockquote>
|
|
|
|
In the function declaration, the return type and any specifiers
|
|
(extern or static) should appear on a separate line followed by the
|
|
function name and arguments as shown above. The left curly brace
|
|
should appear on the same line as the function name.
|
|
|
|
<p>
|
|
Function declarations should <b>NOT</b> use the pre-ANSI function
|
|
declaration syntax. The ANSI standard has been around long enough for
|
|
this to be a non-issue.
|
|
|
|
<h2>8. Naming Conventions</h2>
|
|
|
|
The following conventions are used to name various objects throughout SWIG.
|
|
|
|
<h4>Functions</h4>
|
|
|
|
Functions should consist of the module name and the function name separated by an underscore like this:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
Preprocessor_define()
|
|
Swig_add_directory()
|
|
</pre>
|
|
</blockquote>
|
|
|
|
In general, the module name should match the name of the module
|
|
subdirectory and the function name should be in all lowercase with
|
|
words separated by underscores.
|
|
|
|
<h4>Structures and Types</h4>
|
|
|
|
If your module defines new structures, the structure name should include the name of the
|
|
module and the name of the structure appended together like this:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
typedef struct SwigScanner {
|
|
...
|
|
} SwigScanner;
|
|
|
|
typedef struct LParseType {
|
|
...
|
|
} LParseType;
|
|
</pre>
|
|
</blockquote>
|
|
|
|
In this case, both the name of the module and the type should be capitalized. Also, whenever
|
|
possible, you should use the "typedef struct Name { ... } Name" form when defining new
|
|
data structures.
|
|
|
|
<h4>Global Variables</h4>
|
|
|
|
Global variables should be avoided if at all possible. However, if you must use a global
|
|
variable, please prepend the module name and use the same naming scheme as for functions.
|
|
|
|
<h4>Constants</h4>
|
|
|
|
Constants should be created using #define and should be in all caps like this:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
#define SWIG_TOKEN_LPAREN 1
|
|
</pre>
|
|
</blockquote>
|
|
|
|
Separate words in a constant should be separated by underscores as with functions.
|
|
|
|
<h4>Structure members</h4>
|
|
|
|
Structure members should be in all lower-case and follow the same word-separation convention
|
|
as for function names. However, the module name does not have to be included.
|
|
For example:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
typedef struct SwigScanner {
|
|
DOH *text; /* Current token value */
|
|
DOH *scanobjs; /* Objects being scanned */
|
|
DOH *str; /* Current object being scanned */
|
|
char *idstart; /* Optional identifier start characters */
|
|
int next_token; /* Next token to be returned */
|
|
int start_line; /* Starting line of certain declarations */
|
|
int yylen; /* Length of text pushed into text */
|
|
DOH *file; /* Current file name */
|
|
} SwigScanner;
|
|
</pre>
|
|
</blockquote>
|
|
|
|
<h4>Static Functions and Variables </h4>
|
|
|
|
Static declarations are free to use any naming convention that is appropriate. However, most
|
|
existing parts of SWIG use lower-case names and follow the same convention as described for functions.
|
|
|
|
<h2>9. Visibility</h2>
|
|
|
|
Modules should keep the following rules in mind when exposing their internals:
|
|
|
|
<ul>
|
|
<li>Only publicly accessible functions should be included in the module header file.
|
|
<li>All non-static declarations must be prepended with some form of the module name
|
|
to avoid potential linker namespace conflicts with other modules.
|
|
<li>Modules should not expose global variables or use global variables in their
|
|
public interface.
|
|
<li>Similarly, modules should discourage the direct manipulation of data contained
|
|
within data structures in favor of using function calls instead. For example,
|
|
instead of providing a user with a structure like this:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
typedef struct Foo {
|
|
int line;
|
|
} Foo;
|
|
</pre>
|
|
</blockquote>
|
|
|
|
It is better to hide the implementation of Foo and provide an
|
|
function-call interface like this:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
typedef struct Foo Foo;
|
|
extern int Foo_getline(Foo *f);
|
|
extern void Foo_setline(Foo *f, int line);
|
|
</pre>
|
|
</blockquote>
|
|
|
|
Although this results in worse performance, there are many practical
|
|
reasons for doing this. The most important reason is that it allows
|
|
you to change the internal representation of Foo without breaking all
|
|
of the other modules or having to recompile the entire universe after
|
|
making your changes.
|
|
|
|
</ul>
|
|
|
|
<h2>10. Guile Support Internals</h2>
|
|
|
|
Please direct questions about this section to
|
|
<a href="mailto:ttn@glug.org">ttn@glug.org</a>.
|
|
Last update: 2000-04-03 05:27:34-0700.
|
|
|
|
<h3>Meaning of "Module"</h3>
|
|
|
|
<p>
|
|
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".
|
|
|
|
<h3>Linkage</h3>
|
|
|
|
<p>
|
|
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 <b>linkage</b>. The default
|
|
linkage is the simplest; nothing special is done. In this case
|
|
<code>SWIG_init()</code> is provided and users must do something like this:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
(define my-so (dynamic-link "./example.so"))
|
|
(dynamic-call "SWIG_init" my-so)
|
|
</pre>
|
|
</blockquote>
|
|
|
|
At this time, the name <code>SWIG_init</code> 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 <code>dynamic-link</code> and
|
|
<code>dynamic-call</code>, as shown here.
|
|
|
|
<p>
|
|
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.
|
|
|
|
<p>
|
|
The only other linkage supported at this time creates shared object libraries
|
|
suitable for use by hobbit's <code>(hobbit4d link)</code> 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]
|
|
|
|
<blockquote>
|
|
<pre>
|
|
swig -guile -package my/lib foo.i
|
|
swig -guile -package my/lib -module foo foo.i
|
|
</pre>
|
|
</blockquote>
|
|
|
|
would create module <code>(my lib foo)</code> (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.
|
|
|
|
<p>
|
|
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
|
|
<code>GUILE::emit_linkage()</code>.
|
|
|
|
<h3>Underscore Folding</h3>
|
|
|
|
<p>
|
|
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.
|
|
|
|
<h3>Typemaps</h3>
|
|
|
|
<p>
|
|
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:
|
|
|
|
<blockquote>
|
|
<pre>
|
|
%include guile/typemaps.i
|
|
</pre>
|
|
</blockquote>
|
|
|
|
in foo.i. This may change in the future.
|
|
|
|
<h3>Smobs</h3>
|
|
|
|
<p>
|
|
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.
|
|
|
|
<p>
|
|
Currently, one wrapper module must be generated without
|
|
<code>-c</code> and compiled with <code>-DSWIG_GLOBAL</code>, all the
|
|
other wrapper modules must be generated with <code>-c</code>. Maybe
|
|
one should move all the global helper functions that come from
|
|
<code>guile.swg</code> into a library, which is built by <code>make
|
|
runtime</code>.
|
|
|
|
<p>
|
|
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.
|
|
|
|
<p>
|
|
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. <code>SWIG_Guile_Init()</code> registers a smob type named
|
|
"swig" with Guile; its type tag is stored in the variable
|
|
<code>swig_tag</code>. 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: <code>#<swig struct xyzzy * 0x1234affe></code> Two of
|
|
them are <code>equal?</code> if and only if they have the same type
|
|
and value.
|
|
|
|
<p>
|
|
To construct a Scheme object from a C pointer, the wrapper code calls
|
|
the function <code>SWIG_Guile_MakePtr_Str()</code>, 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.
|
|
|
|
<p>
|
|
To get the pointer represented by a smob, the wrapper code calls the
|
|
function <code>SWIG_Guile_GetPtr_Str</code>, 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 <code>wrong-type-arg</code> exception is raised.
|
|
|
|
<h3>Exception Handling</h3>
|
|
|
|
<p>
|
|
SWIG code calls <code>scm_error</code> on exception, using the following
|
|
mapping:
|
|
|
|
<pre>
|
|
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");
|
|
</pre>
|
|
|
|
<p>
|
|
The default when not specified here is to use "swig-error".
|
|
See Lib/exception.i for details.
|
|
|
|
|
|
<h2>11. Miscellaneous </h2>
|
|
|
|
<ul>
|
|
<li> Do not use the ternary ?: operator. It is unnecessarily error prone,
|
|
hard for people to read, and hard to maintain code that uses it.
|
|
</ul>
|
|
|
|
</body>
|
|
</html>
|