s c h e m e w i k i . o r g

/ Trash.InterfacingWithC

This Web


WebHome 
WebChanges 
WebTopicList 
WebStatistics 

All Webs


Chicken
Cookbook
Erlang
Know
Main
Plugins
Sandbox
Scm
TWiki
Trash  

Schematics


Schematics Home
TWiki Shorthand

Offsite Links


Schemers.org
Lambda the Ultimate
twiki.org

Interfacing with C libraries

Problem

We want to use C libraries from Scheme without writing C code ourselves.

Solution

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:

(g_print "Hello, C")

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!")

Discussion

Should this be a category? I'd like to add other recipes related to the FFI library.


Contributors

-- DanielSilva - 23 Sep 2004

Comments about this recipe

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