[plt-scheme] Using FFI with complex structures and input/output parameters?

From: Eli Barzilay (eli at barzilay.org)
Date: Thu Jul 2 12:01:10 EDT 2009

On Jul  2, Elena Garrulo wrote:
> Well, I finally nailed it down.  It would look like this (code
> shrinked down from major example, not tested!) :
> ;; void fill_buffer (BYTE* buffer, DWORD* buffer_size);
> (define fill_buffer
>   (get-ffi-obj "fill_buffer"
>                my_dll
>                (_fun
>                 (buffer : _pointer)
>                 (buffer_size : ((_ptr io _DWORD)))
>                 -> _void
>                 -> (list buffer_size)))) ;; <- OUTPUT?

I'm still not sure about the point of this -- is the foreign function
supposed to put data in your block and tell you the size of the data
through the extra return value (eg, instead of using 0 as a
terminator, or instead of you giving it a block of the right size)?
IMO, this doesn't sound like a good API.

In any case, there's no need to return a list of the size.  Also, you
might just copy the range of data to a new buffer and return that,
instead of using the input buffer.

> Which you would call like this:
> (define buffer_size 1000) ;; Pick your buffer size.
> ;; Buffer allocation.
> (define buffer (malloc _byte (* buffer_size (ctype-sizeof  _byte))))

This could be simpler with `make-bytes'.

> ;; call "fill_buffer" and retrieve size of result.
> (set! buffer_size (car (fill_buffer buffer buffer_size)))
> ;; resize buffer accordingly
> (set! buffer (cblock->vector buffer _byte buffer_size))

And if the above is done, then you can just use subbytes.  You could
also do both the buffer and pointer allocation, and dereferencing in
the definition of the function, so you won't need any of this outside.

> ;; remember to (free buffer) when you're done.

No, you don't need to do that.

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

Posted on the users mailing list.