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!")
Should this be a category? I'd like to add other recipes related to the FFI library.
--
DanielSilva - 23 Sep 2004
Yes, adding a new category "Foreign Librares - FFI" seems to be the
proper thing to do.
--
JensAxelSoegaard - 24 Sep 2004
I've added
ForeignInterfaceChapter? and
ForeignInterfaceBasics? (a copy of this).
--
DanielSilva - 24 Sep 2004
I don't think it is a good idea to make copies. If someone decides to
make changes, then they need to change two pages in stead of one. Or worse -
they might even not know the other page exists.
--
JensAxelSoegaard - 26 Sep 2004
Oh, I was making sure first that the new page was alright. This one should be deleted now. How do I do that?
--
DanielSilva - 27 Sep 2004
That's a good question.
--
JensAxelSoegaard - 26 Sep 2004
To delete, click on the "More" tab at the top of the page and Move this page to the Trash web.
--
NoelWelsh - 28 Sep 2004
| CookbookForm? |
| TopicType?: | Recipe |
| ParentTopic?: | |
| TopicOrder?: | 999 |
© 2004 by the contributing authors. / You are Main.guest