We want to use C libraries from Scheme without writing C code ourselves.
We'll use PLT Scheme's
foreign module to drive
libffi.
Note: the foreign module is currently only available for v299.
The
foreign module is part of the
MzScheme core library, so we'll require it with:
(require (lib "foreign.ss"))
We can load a C library with
ffi-lib:
(define glib (ffi-lib "libglib-2.0.so"))
The GLib library exports a function,
g_print, that sends a formatted message to a print handler (usually a stdout printer).
Its signature is:
void g_print(const gchar* format, ...);
Let's ignore the varargs and treat the
gchar* type as a constant C character string. The function type we care about is then:
g_print: string -> void
We can fetch it from the loaded library with
get-ffi-obj:
(define g_print
(get-ffi-obj "g_print" glib
(_fun _string -> _void)))
There are three arguments to
get-ffi-obj: the name of the C object we're importing, the library object to load it from, and its ffi type.
The ffi type
(_fun _string -> _void) is a function that consumes a string and has no return value. Note that ffi type names start with an underscore.
Now we can use
g_print as if it were a Scheme function:
We can also use Scheme functions as C callbacks. We'll make use of one right now to redirect the output from
g_print. GLib allows us to install a print handler with
g_set_print_handler:
GPrintFunc g_set_print_handler(GPrintFunc handler);
The
GPrintFunc type is that of a function that only consumes a string. We'll define both
GPrintFunc and
g_set_print_handler in Scheme:
(define _GPrintFunc (_fun _string -> _void))
(define g_set_print_handler
(get-ffi-obj "g_set_print_handler" glib
(_fun _GPrintFunc -> _pointer)))
Now let's install a print handler and test it:
(require (lib "mred.ss" "mred"))
(g_set_print_handler (lambda (str)
(message-box "GLib message" str)))
(g_print "Hello from C!")
--
DanielSilva - 24 Sep 2004