This section details guile-specific support in SWIG.
G.1 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".
G.2 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.
SWIG_init()
is exported. Simple linkage
can be used in several ways:
SWIG_init()
in the
inner_main()
function. See the "simple" and "matrix" examples under
Examples/guile
.
define-module
, containing both Scheme code and
bindings made by SWIG; you want to load the SWIG modules as shared
libraries into Guile.
Newer Guile versions provide a shorthand for(define-module (my module)) (define my-so (dynamic-link "./example.so")) (dynamic-call "SWIG_init" my-so) ; make SWIG bindings ;; Scheme definitions can go here
dynamic-link
and dynamic-call
:
You need to explicitly export those bindings made by SWIG that you want to import into other modules:(load-extension "./example.so" "SWIG_init")
In this example, the procedures(export foo bar)
foo
and bar
would be exported. Alternatively, you can export all bindings with the
following module-system hack:
(module-map (lambda (sym var) (module-export! (current-module) (list sym))) (current-module))
SWIG can also generate this Scheme stub (from
define-module
up to export
)
semi-automagically if you pass it the command-line argument
-scmstub foo.scm
. Since SWIG doesn't know how
to load your extension module (with dynamic-link
or
load-extension
), you need to supply this
information by including a directive like this in the interface file:
(The%scheme %{ (load-extension "./example.so" "SWIG_init") %}
%scheme
directive allows to insert arbitrary Scheme
code into the generated file foo.scm
; it is
placed between the define-module
form and the
export
form.)
If you want to include several SWIG modules, you would need to rename
SWIG_init
via a preprocessor define to avoid symbol
clashes. For this case, however, passive linkage is available.
Passive linkage is just like simple linkage, but it generates an initialization function whose name is derived from the module and package name (see below).
You should use passive linkage rather than simple linkage when you are using multiple modules.
SWIG can also generate wrapper code that does all the Guile module
declarations on its own if you pass it the -Linkage
module
command-line option. This requires Guile 1.5.0 or later.
The module name is set with the -package
and
-module
command-line options. Suppose you want to define
a module with name (my lib foo)
; then you would have to
pass the options -package my/lib -module
foo
. Note that the last part of the name can also be set
via the SWIG directive %module
.
You can use this linkage in several ways:
scm_init_my_modules_foo_module
in the inner_main()
function.
Newer Guile versions have a shorthand procedure for this:(define my-so (dynamic-link "./foo.so")) ;; create new module and put bindings there: (dynamic-call "scm_init_my_modules_foo_module" my-so)
(load-extension "./foo.so" "scm_init_my_modules_foo_module")
Guile used to support an autoloading facility for object-code
modules. This support has been marked deprecated in version 1.4.1 and
is going to disappear sooner or later. SWIG still supports building
auto-loading modules if you pass it the -Linkage ltdlmod
command-line option.
Auto-loading worked like this: Suppose a module with name (my
lib foo)
is required and not loaded yet. Guile will then search
all directories in its search path
for a Scheme file my/modules/foo.scm
or a shared library
my/modules/libfoo.so
(or
my/modules/libfoo.la
;
see the GNU libtool documentation). If a
shared library is found that contains the symbol
scm_init_my_modules_foo_module
,
the library is loaded, and the function at that symbol is called with
no arguments in order to initialize the module.
When invoked with the -Linkage ltdlmod
command-line
option, SWIG generates an exported module initialization function with
an apropriate name.
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:
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.
-c
command-line argument. Compile all wrapper files
with the C compiler switch -DSWIG_GLOBAL
.
-c
command-line argument and compile all wrapper files with the C
compiler switch -DSWIG_GLOBAL
. Then link against the
runtime library libswigguile
, which is built by
make runtime
. The needed linker flags are reported by
SWIG if you invoke it with the -guile -ldflags
command-line arguments.
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.
You can use the SWIG directives %name
and
%rename
to specify the Guile name of the wrapped
functions and variables (see CHANGES).
G.4 Typemaps
The Guile module handles all types via typemaps. This
information is read from Lib/guile/typemaps.i
.
Some non-standard typemap substitutions are supported:
$descriptor
expands to a type descriptor for use with
the SWIG_Guile_MakePtr()
and
SWIG_Guile_GetPtr
functions.
$*descriptor
expands to a
descriptor for the direct base type (i.e., one pointer is stripped),
whereas $basedescriptor
expands to a
descriptor for the base type (i.e., all pointers are stripped).
A function returning void
(more precisely, a function
whose out
typemap returns GH_UNSPECIFIED
) is
treated as returning no values. In argout
typemaps, one
can use the macro GUILE_APPEND_RESULT
in order to append
a value to the list of function return values.
Multiple values can be passed up to Scheme in one of three ways:
%values_as_list;
vectors instead of lists will be used.%values_as_vector;
multiple values are passed to the multiple-value continuation, as created by%multiple_values;
call-with-values
or the
convenience macro receive
. The latter is available if you
issue (use-modules (srfi srfi-8))
. Assuming that your
divide
function
wants to return two values, a quotient and a remainder, you can write:
In(receive (quotient remainder) (divide 35 17) body...)
body
, the first result of
divide
will be bound to the variable
quotient
, and the second result to remainder
.
For pointer types, SWIG uses Guile smobs.
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()
, passing a pointer to a
struct representing the pointer type. The type index to store in the
upper half of the CAR is read from this struct.
To get the pointer represented by a smob, the wrapper code calls the
function SWIG_Guile_GetPtr
, passing a pointer to a struct
representing the expected pointer type. If the
Scheme object passed was not a SWIG smob representing a compatible
pointer, a wrong-type-arg
exception is raised.
G.6 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.
G.7 Procedure documentation
If invoked with the command-line option -procdoc
file
, SWIG creates documentation strings for the
generated wrapper functions, describing the procedure signature and
return value, and writes them to file. You need Guile 1.4
or later to make use of the documentation files.
SWIG can generate documentation strings in three formats, which are
selected via the command-line option -procdocformat
format
:
guile-1.4
(default): Generates a format suitable for Guile 1.4.
plain
: Generates a format suitable for Guile 1.4.1 and
later.
texinfo
: Generates texinfo source, which must be run
through texinfo in order to get a format suitable for Guile 1.4.1 and
later.
You need to register the generated documentation file with Guile like this:
(use-modules (ice-9 documentation)) (set! documentation-files (cons "file" documentation-files))
Documentation strings can be configured using the Guile-specific
typemaps indoc
, outdoc
,
argoutdoc
, varindoc
, and
varoutdoc
. See Lib/guile/typemaps.i
for
details.
G.8 Procedures with setters
For global variables, SWIG creates a single wrapper procedure
(variable :optional value)
, which is used for
both getting and setting the value. For struct members, SWIG creates
two wrapper procedures (struct-member-get
pointer)
and (struct-member-set pointer value)
.
If invoked with the command-line option -emit-setters
,
SWIG will additionally create procedures with setters. For global
variables, the procedure-with-setter variable
is created, so you can use (variable)
to get
the value and (set! (variable)
value)
to set it. For struct members, the
procedure-with-setter struct-member
is created, so you can use (struct-member
pointer)
to get the value and (set!
(struct-member pointer)
value)
to set it.