This chapter describes SWIG's support of CHICKEN. CHICKEN is a Scheme-to-C compiler supporting most of the language features as defined in the Revised^5 Report on Scheme. Its main attributes are that it
CHICKEN support was introduced to SWIG in version 1.3.18. SWIG
relies on some recent additions to CHICKEN, which are only
present in releases of CHICKEN with version number
greater than or equal to 1.0.
CHICKEN can be downloaded from http://www.call-with-current-continuation.org/chicken.html
You may want to look at any of the examples in Examples/chicken/
or Examples/GIFPlot/Chicken for the basic steps to run SWIG
CHICKEN.
We will generically refer to the wrapper as the
generated files.
To run SWIG CHICKEN in C mode, use the -chicken option.
To allow the wrapper to take advantage of future CHICKEN code generation improvements, part of the wrapper is direct CHICKEN function calls (example_wrap.c) and part is CHICKEN Scheme (example.scm). The basic Scheme code must be compiled to C using your system's CHICKEN compiler.% swig -chicken example.i
So for the C mode of SWIG CHICKEN, example_wrap.c and oexample.c are the files that must be compiled to object files and linked into your project.% chicken example.scm -output-file oexample.c
To run SWIG CHICKEN in C++ mode, use the -chicken -c++ option.
This will generate example_wrap.cxx, example.scm, example-generic.scm and example-clos.scm. The basic Scheme code must be compiled to C using your system's CHICKEN compiler.% swig -chicken -c++ example.i
So for the C++ mode of SWIG CHICKEN, example_wrap.cxx and oexample.c are the files that must be compiled to object files and linked into your project.% chicken example.scm -output-file oexample.c
Given a C variable, function or constant declaration named
Foo_Bar_to_Foo_Baz, the declaration will be available
in CHICKEN as an identifier ending with
foo-bar->foo-baz. That is, an underscore is converted
to a dash, '_to_' is converted to an arro, and all characters
are sent to lowercase.
Additionally, there is a mixed mode that can be
specified with the -mixed option on the SWIG command
line. In this mode, the above rules apply with the addition
that changes in case are indications to SWIG CHICKEN to place a
dash in the CHICKEN identifier. For example, a C declartaion
named someDeclaration_xyz will be available as the
CHICKEN identifier ending with some-declaration-xyz.
You may control what the CHICKEN identifier will be by using the
%rename SWIG directive in the SWIG interface file.
SWIG CHICKEN does not use the standard CHICKEN module system (which has been deprecated); instead, it uses a prefix system. Specifying the module name as 'example' in SWIG CHICKEN can be done using either of:
Constants may be created using any of the four constructs in the interface file:
#define MYCONSTANT1 ...
%constant int MYCONSTANT2 = ...
const int MYCONSTANT3 = ...
enum { MYCONSTANT4 = ... };
Variables are accessed using the full parameter form. For example, to set the C variable "int my_variable;", use the Scheme form (my-variable 2345). To get the C variable, use (my-variable).
C functions declared in the SWIG interface file will have
corresponding CHICKEN Scheme procedures. For example, the C
function "int sqrt(double x);" will be available using the
Scheme form (sqrt 2345.0). A void
return
value will give C_SCHEME_UNDEFINED as a result.
A function may return more than one value by using the
OUTPUT
specifier (see Lib/chicken/typemaps.i).
They will be returned as a Scheme list if there is more than one
result (that is, a non-void return value and at least one argout
parameter, or a void return value and at least two argout
parameters).
The author of TinyCLOS, Gregor Kiczales, describes TinyCLOS as:
Tiny CLOS is a Scheme implementation of a `kernelized' CLOS, with a metaobject protocol. The implementation is even simpler than the simple CLOS found in `The Art of the Metaobject Protocol,' weighing in at around 850 lines of code, including (some) comments and documentation.Almost all good Scheme books describe how to use metaobjects and generic procedures to implement an object-oriented Scheme system. Please consult a Scheme book if you are unfamiliar with the concept.
Please refer to CHICKEN - A practical and portable Scheme system - User's manual for detailed help on how to compile C code for use in a CHICKEN program. Briefly, to compile C code, be sure to add `chicken-config -cflags` or `chicken-config -shared -cflags` to your compiler options. Use the -shared option if you want to create a dynamically loadable module. You might also want to use the much simpler csc or csc.bat.
Please refer to CHICKEN - A practical and portable Scheme system - User's manual for detailed help on how to link object files to create a CHICKEN Scheme program. Briefly, to link object files, be sure to add `chicken-config -extra-libs -libs` or `chicken-config -shared -extra-libs -libs`to your linker options. Use the -shared option if you want to create a dynamically loadable module.
All the following examples assume that the module is named 'example' and the following occurs when run:
Substitute /usr/local/share/chicken as appropriate for your platform.% chicken-config -home CHICKEN_HOME=/usr/local/share/chicken
We will assume your files are in a directory /home/jonah/examples. Make a file as follows:
;; precsi.scm (declare (unit precsi)) (declare (uses example)) ;; any other code you want run before the main interpreter is executedRun SWIG on your interface file as usual, create the 2 wrapper object files, and then either
or% cd /usr/local/share/chicken % chicken /usr/local/share/chicken/src/csi.scm -optimize-level 3 -quiet \ -include-path /usr/local/share/chicken/src \ -prologue /usr/local/share/chicken/src/build.scm \ -prelude "(declare (uses posix precsi))" \ -output-file /home/jonah/examples/csi-example.c % cd /home/jonah/examples % chicken precsi.scm -optimize-level 3 --explicit-use \ -output-file precsi.c % gcc precsi.c csi.c wrapper_object_files \ `chicken-config -libs` `chicken-config -extra-libs` -o csi-example
% extend-csi precsi -output-file csi-example
The Chicken module handles all types via typemaps. This information is
read from Lib/chicken/typemaps.i
and
Lib/chicken/chicken.swg
.
Two Chicken-specific typemaps are supported:
clos_in
and clos_out
. They are for
converting TinyCLOS to and from low-level CHICKEN SWIG. Here is
a quick example:
The/* Let "Shape" objects be converted back and forth from TinyCLOS into low-level CHICKEN SWIG procedures */ %typemap(clos_in) Shape * = SIMPLE_CLOS_OBJECT *; %typemap(clos_out) Shape * = SIMPLE_CLOS_OBJECT *;
SIMPLE_CLOS_OBJECT
will generally be all that
is needed ... the definition of this is as follows:
Now, in the example using "Shape" objects, all objects instantiated from Shape or any of its subclasses fully known to SWIG will have correct TinyCLOS representations based on/* TinyCLOS <--> Low-level CHICKEN */ %typemap("clos_in") SIMPLE_CLOS_OBJECT * "(slot-ref $input (quote this))" %typemap("clos_out") SIMPLE_CLOS_OBJECT * "(make $class (quote this) $1)"
SIMPLE_CLOS_OBJECT
. SWIG "knows" the classes that
are exposed in the SWIG interface file; it "fully knows" only
those classes that are not forward declarations.
/* FILE: vtkObject.h */ class vtkObject { // ... };
/* FILE: vtkWindow.h */ #include "vtkObject.h" class vtkWindow : public vtkObject { // ... };
/* FILE: vtkViewport.h */ #include "vtkViewport.h" class vtkViewport : public vtkObject { // ... };
/* FILE: vtkRenderWindow.h */ #include "vtkWindow.h" class vtkRenderer; class vtkRenderWindow : public vtkWindow { // ... virtual void AddRenderer (vtkRenderer *rendererArg); // ... };
/* FILE: vtkRenderer.h */ #include "vtkViewport.h" class vtkRenderWindow; class vtkRenderer : public vtkViewport { // ... void SetRenderWindow(vtkRenderWindow *); // ... };
After SWIG processes/* FILE: vtk.i; SWIG interface file */ %typemap(clos_in) vtkObject * = SIMPLE_CLOS_OBJECT *; %typemap(clos_out) vtkObject * = SIMPLE_CLOS_OBJECT *; %include "vtkObject.h" %include "vtkWindow.h" %include "vtkViewport.h" %include "vtkRenderWindow.h" %include "vtkRenderer.h"
vtkObject.h
(from the
%include "vtkObject.h" line), SWIG will have the complete
definition of the vtkObject
class because
vtkObject
does not contain any references to any
other classes. As it reads vtkWindow.h
and
vtkViewport.h
, it will already have the definition of
vtkObject
, so it will not need a clos_in
or clos_out
typemap for the vtkWindow
or
vtkViewport
subclasses of vtkObject
.
However, by the time SWIG gets to %include
"vtkRenderWindow.h", it will not have the definition for the
vtkRenderer
class, even though it is used by
vtkRenderWindow
. We therefore must
put in clos_in/clos_out
typemaps for
vtkRenderer
.
For pointer types, SWIG uses CHICKEN tagged pointers. A tagged pointer is an ordinary CHICKEN pointer with an extra slot for an arbitrary Scheme object. With SWIG CHICKEN, this Scheme object is a reference to a type-info structure. So each pointer used as input or output from the SWIG-generated CHICKEN wrappers will have type information attached to it. This will let the wrappers correctly determine which method should be called according to the object type hierarchy exposed in the SWIG interface files.
To construct a Scheme object from a C pointer, the wrapper code
calls the function swig_new_pointer_obj()
, passing
stack allocation space of size SWIG_ALLOCSZ_POINTER (see
definition in Lib/chicken/chickenrun.swg and also
C_alloc()
in the CHICKEN documentation) and a
pointer to a struct representing the pointer type.
To get the pointer represented by a CHICKEN tagged pointer, the
wrapper code calls the function swig_convert_ptr()
,
passing a pointer to a struct representing the expected pointer
type. If the Scheme object passed was not a tagged pointer
representing a compatible pointer, a non-zero value is returned.
Warning: The Chicken typechecking code seems to be broken (Bug #782468), so that type errors may not be reported.