[plt-scheme] FFI - garbage collection

From: Eli Barzilay (eli at barzilay.org)
Date: Tue Oct 11 22:37:39 EDT 2005

On Oct 12, Yoav Goldberg wrote:
> > > Hi.
> > > I am wrapping a dll using the v299 ffi.
> > > As a part of my code, I have a c function that returns a pointer to
> > > a structure:
> > > (define-syntax defmshare
> > >   (syntax-rules ()
> > >      ((defmshare scheme-name libname type ...)
> > >       (define scheme-name (get-ffi-obj libname mshare (type ...))))))
> > >
> > > (defmshare MidiNewEv* "MidiNewEv" _fun _short -> _TMidiEv-pointer)
> > (Ugh, if you went all the way to a macro, why not make the macro add
> > the _fun?  Otherwise it doesn't do much, and actually looks clearer
> > with the parens.)
> I find it more readable with the _fun and without the parens.. And
> the macro is used just to save some typing..

(Look at the code in the ffi collection.)

> Yes, but unlike C, it is very easy to create these things in Scheme
> without any handle, and so there is no way to free them: (MidiNewEv
> 4).

The exact same thing can be done in C.  Just move the paren over.

> > Perhaps the library is meant to be used in a way that you never
> > create these objects unless you send them?  This means that
> > another way to organize things is to have some Scheme objects that
> > stand for these TMidiEv objects -- then, you do a wrapper for
> > MidiSendIm that will get one of these Scheme objects, generate a
> > real TMidiEv object, initialize it, and immediately send it over
> > to MidiSendIm.
> This is a possibility. Another option I though of after I sent the
> mail was to use the library function "MidiCopyEv", and wrap
> MidiSendIm so it will be passed a copy instead of the original:
> (let ((origMidiSendIm MidiSendIm))
>    (set! MidiSendIm
>        (lambda (chan event)
>            (origMidiSendIm chan (MidiCopyEv event)))))
> This seems very similar (and also quite the opposite?) to what you
> suggested.  Which do you think will be more efficiant?  Which do you
> think is nicer?

Better to keep it to Scheme values as long as possible.  This way, if
you do some extensions, they're easier.

> > One thing you have to be aware of, is that allocation using the
> > Scheme `malloc' goes through the GC by default.  I don't think
> > that it will be a good idea to pass such objects to a C library
> > that will try to free them...
> What is the Scheme "malloc", and what does it allocate?

It's the foreign.ss interface to the built-in C malloc (actually, to a
few of them).  If you call a foreign function that allocates
something, it will no do it through the GC, so you need the
registration.  But, if you use something like (malloc _MidiEv), then
the allocation happens through the GC and will be collected

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

Posted on the users mailing list.