[plt-scheme] Handling passing parameters by reference in foreign.ss

From: Eli Barzilay (eli at barzilay.org)
Date: Fri Apr 15 12:48:52 EDT 2005

On Apr 15, Paulo Jorge de Oliveira Cantante de Matos wrote:
> I decided to try out foreign.ss, and so I picked Imlib2 API and
> created a scheme interface using foreign.ss (which is great, by
> the way) for most of the functions now (really nice to see it
> works also, eheh) but I'm also having problems with some
> function which get parameters by reference like the following:
> void imlib_context_get_color(int *red, int *green, int *blue,
> int *alpha);
> 
> In C it is straightforward to see how it works but I'm having a
> hard time on how to create an interface in scheme with
> foreign.ss for this function.
> 
> Any suggestions would be appreciated.

Well, you need to malloc three integers and send them to the function,
then pull out the values from the malloced pointers.  This is
automatically done in foreign, and described in the manual, but here's
a quick "tutorial" anyway, since it seems that many people don't use
it in places they should...

The type that you want to use is one of these special custom types
which is a kind of a type macro which is available only in a _fun
context.  Specifically, you want a (_ptr o _int) which is an output
pointer of integer, which does exactly this thing of dealing with C
functions that return multiple values through pointes.  So, say that
you have a C function that returns two values through pointers and a
status success/failure boolean:

  int foo(int *x, int *y) { *x = 1; *y = 2; return 1; }

the Scheme interface will initially look like this:

  (define foo (get-ffi-obj "foo" "x.so"
                (_fun (_ptr o _int) (_ptr o _int) -> _bool)))

Now, this will do the right thing but you can't access these values
yet, and you simply get the status output.  The first step in using
the returned values is giving them names:

  (define foo (get-ffi-obj "foo" "x.so"
                (_fun (x : (_ptr o _int)) (y : (_ptr o _int))
                      -> _bool)))

but this function still returns the same status value...  For this,
there is a specification that says that _bool is the return value of
the foreign function, but what you actually want to return is some
specific expression:

  (define foo (get-ffi-obj "foo" "x.so"
                (_fun (x : (_ptr o _int)) (y : (_ptr o _int))
                      -> _bool
                      -> (list x y))))

As you can see -- it is easy to make the Scheme interface return a
list of the values, a multiple-value result or whatever.  Finally, you
might need the actual return value of the function so you can raise an
error in case one occured.  For this you need to name the result value
too:

  (define foo (get-ffi-obj "foo" "x.so"
                (_fun (x : (_ptr o _int)) (y : (_ptr o _int))
                      -> (status : _bool)
                      -> (if status (list x y) (error 'foo "boom")))))

It is also possible to define some _status type which is based on
_bool so you get an error automatically if a _status result is not
#t.  See the ffi collection for examples.

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



Posted on the users mailing list.