[plt-scheme] C++ Bindings using FFI

From: Eli Barzilay (eli at barzilay.org)
Date: Tue May 9 17:00:04 EDT 2006

On May  8, Hans Oesterholt-Dijkema wrote:
> True. But note that this little file with 628 lines of type mappings
> is the only one I need to generate all code that is needed from the
> 21.000 lines of Gtk+ headers.
> I imagine there would also be typemap code needed for the FFI, but
> maybe much simpler.

Right -- *much*.

> > (Using SWIG to generate Scheme glue code means that you only use
> > its parsing ability.)
> No. Not really. You need to write a scheme generator. Weather you
> write a C generator or a Scheme generator doesn't really matter, or
> does it?

The above is the reason that I said this.  When you deal with
converting between different types, it is much easier to do things in
Scheme than it is in C.  Since SWIG doesn't give you (again, IIUC)
much beyond hooks to put type conversion code in any language you want
to work with, then it will most likely be more difficult to write such
code snippets for SWIG than writing the code using the foreign
interface.  (But all that is just assumptions.)

> > Yes, I'm aware of that.  The point I made is different: say that
> > you write an interface for `libfoo', which provides a `foo'
> > int->int function -- SWIG knows about this from the header file
> > and will generate the Scheme glue code.  Later on I download your
> > code, but I have an older version of libfoo, where `foo' is
> > char->char.  (More than that -- I might not have the libfoo header
> > files.)
> >   
> Users never need the libfoo header files. Because the swig code has
> been already generated.

Only if the generated code matches the libfoo version you have on your
machine.  If there is any interface change like I describe above, the
generated interface code is likely to break.

> So, maybe I'm missing a link here. Does the FFI know from the library, 
> how a function is typed?

(There is no such information in shared libraries.  That's exactly the

On May  9, Paulo J. Matos wrote:
> I've never used SWIG so this comment might be biased and brutally
> wrong.  As far as I have understood libffi opens the library in
> scheme, reads the file and lets you in Scheme create bindings
> accessing its internals, so it seems to have a dynamic access to the
> library, if the library changes, the bindings change with it.

Not really -- besides the fact that some function exists or not, you
cannot tell what the types are.  This means that header files are the
language that is used to describe libraries.

> In Swig, the header info given by the typemaps are passed to swig
> which parses the headers or whatever and generates the C code for
> mzscheme to generate the bindings for the library, which means that
> if the lib changes you have to rerun swig on the headers and
> typemaps to have new bindings, so it generates 'static bindings' in
> comparison with libffi.

So this would be an advantage for the Scheme interface only if there
was some way to know at run-time the types that are used.  Like I
said, this almost never happens, and even if we add the ability to
parse header files, the files themselves might not be present.  An
exception that I mentioned is the ImageMagick interface that provides
a function that describes the `Quantum' type -- see the `_Quantum'
definition in ".../collects/ffi/magick.ss".

On May  9, Hans Oesterholt-Dijkema wrote:
> > At first I would think that libffi would be the way to go. I see
> > no reason for using swig now with libffi available.
> Quite a statement. As far as I know, the FFI also needs to be told
> what type a function in a library is. It would have to know type
> information from the library to make the right calls to functions in
> the library.

True, but the job is much easier when done in Scheme.  For example,
"foreign.ss" has the following definition for `_file' (which is
probably a bad name for this):

  ;; `file' type: path-expands a path string, provide _path too.
  (define* _file (make-ctype _path expand-path #f))

so the new _file type is based on the existing _path, except that it
calls `expand-path' when sending a value to C.  This requires no
additional C knowledge.

> For my mzgtk2 bindings I've patched the mzscheme generator.  It
> generates code, that resolves functions in libraries at runtime
> (using e.g. 'dlopen' on unix). This makes it possible to generate
> binding code from the latest header files of Gtk+, while still being
> able to use the generated code with all versions of Gtk+2.x.  It
> complains only when functions cannot be resolved in older Gtk+
> libraries.

This is another example of a tweak that would be much easier in
Scheme (and will not require changing any existing code).

          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
                  http://www.barzilay.org/                 Maze is Life!

Posted on the users mailing list.