C Integration with Chibi Scheme

Chibi is a very small Scheme library that was built for embedded systems, with an eye towards integration with libraries and such that are already written in C. As such it has very easy methods to call into C functions, and for C functions to call into Scheme. Because the Chibi documentation is a little sparse, this page examines some techniques for doing so.

The Easy Way - Stub Files

Chibi comes with a utility called "genstubs.scm" which can be used to generate an appropriate glue file in C for whatever functions you want to access from within Chibi. First you have to describe the C interface in a stub file. Suppose we have some lame pedagogical functions:

hello(name)
Takes somebody's name, and prints a greeting to that person.
goodbye()
Print a farewell.

Our stub file would look like this:

(define-c void hello-user (string))
(define-c void (so-long goodbye) ())

In order, the elements of define-c are the return type, the name of the function, and the list of arguments the function takes. For the name of the function, note that you don't have to quote it as it appears here; if you do you will get errors when you attempt to compile the resulting C file, as the name of the function binding generated will be "quote." If the symbol for the function name includes dashes, these are replaced with underscores in the actual C implementation. You can make less obvious bridges between Scheme and C using the list form of the name argument, as seen in the second line: the first element is the Scheme name, and the second is the C name.

You can use the "genstubs.scm" file to generate a C file:

$ chibi-scheme .../tools/genstubs.scm test.stub

Here "..." is wherever the Chibi source code is. The result is a file called test.c which contains the Scheme-to-C binding code. Now we need to actually implement those C functions. Let's call this "hello.c":

#include 
#include 

void hello_user(const char *name) {
    printf("Hello, %s.\n", name);
    return;
}

void goodbye() {
    printf("Goodbye!\n");
    return;
}

We compile the hello.c and the test.c files together into a shared library exactly the same as we would always do, but add the chibi-scheme library as well.

$ gcc -fPIC -shared -I.../include/ -L... -o hello.so hello.c test.c -lchibi-scheme

Again, "..." is wherever the Chibi directory is, or if you have installed it system-wide then there's nothing to add for -I and -L. Now you've got a shared object you can load into Chibi like so:

$ chibi-scheme
> (load "./hello.so")
> (hello-user "Taylor")
Hello, Taylor.
> (so-long)
Goodbye!

Building a Module

Chibi supports a simple module system, and you can use it to load shared objects like those produced above and re-export the Scheme functions from them. Let's create a module file, this needs to go into a file called hello.module.

(define-module (hello)
  (export hello-user so-long)
  (include-shared "hello"))

Now from within the same directory, we can again run chibi-scheme and load our new module like we would any other Scheme code.

$ chibi-scheme 
> (import (hello))
> (hello-user "Taylor")
Hello, Taylor.
> (so-long)
Goodbye!