# 22 SWIG and Chicken

- Preliminaries
  - Running SWIG in C mode
  - Running SWIG in C++ mode
- Code Generation
  - Naming Conventions
  - Modules and Prefixes
  - Constants and Variables
  - Functions
- TinyCLOS
- Compilation
- Linkage
  - Customized Interpreter
- Typemaps
- Pointers
- Unsupported features

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

1. generates portable C code
2. includes a customizable interpreter
3. links to C libraries with a simple Foreign Function Interface
4. supports full tail-recursion and first-class continuations

When confronted with a large C library, CHICKEN users can use SWIG to generate CHICKEN wrappers for the C library. However, the real advantage of using SWIG with CHICKEN is its support for C++; object-oriented code is difficult to wrap by hand in CHICKEN.

## 22.1 Preliminaries

CHICKEN support was introduced to SWIG in version 1.3.18. SWIG relies on a recent addition to CHICKEN -- the C_TAGGED_POINTER -- which is only present in CVS versions of CHICKEN dated after February 11, 2003, and in releases of CHICKEN with version number greater than 0.1082.
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.

### 22.1.1 Running SWIG in C mode

To run SWIG CHICKEN in C mode, use the -chicken option.

>     % swig -chicken example.i

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.

>     % chicken example.scm -output-file oexample.c

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.

### 22.1.2 Running SWIG in C++ mode

To run SWIG CHICKEN in C++ mode, use the -chicken -c++ option.

>     % swig -chicken -c++ example.i

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.

>     % chicken example.scm -output-file oexample.c

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.

## 22.2 Code Generation

### 22.2.1 Naming Conventions

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.

### 22.2.2 Modules and Prefixes

SWIG CHICKEN does not use the standard CHICKEN module system; instead, it uses a prefix system. Specifying the module name as 'example' in SWIG CHICKEN can be done using either of:

- Placing `%module example` in the SWIG interface file.
- Using `-module example` on the SWIG command line.

CHICKEN will be able to access the module using the `(declare (uses modulename))` CHICKEN Scheme form.
Normally, for a C declaration `Foo_Bar` with a module name of 'example', the corresponding CHICKEN identifier will be `example-foo-bar`. The module name and a dash is prefixed to the CHICKEN identifier (following normal naming conventions).
You may explicitly override the prefix with the SWIG command line option `-prefix whateverprefix`, or you may remove the prefix with the option `-noprefix`.

### 22.2.3 Constants and Variables

Constants may be created using any of the four constructs in the interface file:

1. `#define MYCONSTANT1 ...`
2. `%constant int MYCONSTANT2 = ...`
3. `const int MYCONSTANT3 = ...`
4. `enum { MYCONSTANT4 = ... };`

In all cases, the constants may be accessed from with CHICKEN using the form `(myconstant1)`; that is, the constants may be accessed using the read-only parameter form.

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)`.

### 22.2.4 Functions

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).

## 22.3 TinyCLOS

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 with a Scheme book if you are unfamiliar with the concept.
CHICKEN has a modified version of TinyCLOS, which SWIG CHICKEN uses in C++ mode. SWIG CHICKEN generates a `xxx_generic.scm` and a `xxx_clos.scm` file, which contain TinyCLOS macros. When using these macros, you will need to `(include "xxx_generic")` all the generic macros your program needs, and then `(include "xxx_clos")` all the metaobject (class) macros your program needs.
SWIG CHICKEN will call the destructor for TinyCLOS objects garbage-collected by CHICKEN. It also allows access to the underlying low-level Scheme procedures with (de)-marshaling of any TinyCLOS parameters. It is best to learn the TinyCLOS system by running the `Examples/chicken/class/` example.

## 22.4 Compilation

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`` to your compiler options.

## 22.5 Linkage

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 -libs` `chicken-config -extra-libs`` to your linker options.

All the following examples assume that the module is named 'example' and the following occurs when run:

>     % chicken-config -home
>     CHICKEN_HOME=/usr/local/share/chicken

Substitute `/usr/local/share/chicken` as appropriate for your platform.

### 22.5.1 Customized Interpreter

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 executed

Run SWIG on your interface file as usual, create the 2 wrapper object files, and then either

>     % cd /usr/local/share/chicken
>     % chicken /usr/local/share/chicken/src/csi.scm -optimize-level 3 -quiet \
>             -include-path /usr/local/share/chicken/src \
>             -postlude "(##csi#run)" \
>             -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

or

>     % extend-csi precsi -output-file csi-example

## 22.6 Typemaps

The Chicken module handles all types via typemaps. This information is read from `Lib/chicken/typemaps.i` and `Lib/chicken/chicken.swg`.
Two non-standard 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:

>     /* 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 *;

The `SIMPLE_CLOS_OBJECT` will generally be all that is needed ... the definition of this is as follows:

>     /* 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)"

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 `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. Have a look at the `Examples/chicken/vtk/example.i` for more information.

## 22.7 Pointers

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.

## 22.8 Unsupported features

- No exception handling.