[plt-scheme] 3m

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Sat Jul 1 22:42:19 EDT 2006

At Sat, 01 Jul 2006 20:57:12 -0400, Jon Rafkind wrote:
> > Both of the major obstacles above have recently become much smaller:
> >
> >  * Using the "foreign.ss" library with 3m is usually not much more
> >    difficult than with CGC. As our library bindings have migrated to
> >    "foreign.ss" (instead of writing the glue in C), using 3m has
> >    become much easier.
> >
> >    Meanwhile, we also have mzc --xform (and a better tool in the
> >    pipeline) for transforming C-implemented glue code to work with 3m.
> >
> >   
> I just tried drscheme3m with the C library, Allegro, that I use for
> doing graphics; drscheme crashed immediately upon initializing the
> Allegro system. I dont understand how using foreign.ss would make 3m
> handle C pointers better, but from the above paragraph I was under the
> impression that it would Just Work( TM ).

It will Just Work ( TM ) for simple uses, where no GCable data is kept
by the foreign library across call. For example, the simple FFI uses in
MzLib's "os.ss" need no special treatment for 3m.

When a library holds a reference to a GCable across interaction with
MzScheme, though, the problem is that the 3m GC might move the object.

For example, in your Allegro binding, GC-managed data gets registered
with the library for use later:

 (define rgb-map (let ((f (malloc _RGBMAP (* 32 32 32))))
                   (cpointer-push-tag! f RGBMAP-tag)
                   (set-RGBMAP-data! f f)
                   (set-ffi-obj! "rgb_map" liballegro _RGBMAP-pointer f)

With CGC, this works ok. The module-level binding to `rgb-map' ensures
that the allocated object won't get collected, and since the GC never
moves objects, the allocated object will stay where the library expects
to find it.

With the 3m GC, although the allocated object won't get GCed, it may be
moved in memory.

One solution to the problem is to allocate the object with 'raw, which
uses the system malloc(), so the resulting object is not GCed (and not
moved). You can attach a finalizer to something that free the
malloc()ed object, maybe like this:

 (define rgb-map (let* ((r (malloc 'raw _RGBMAP (* 32 32 32)))
                        (f (make-rgb-map-wrapper r)))
                   (set-ffi-obj! "rgb_map" liballegro _RGBMAP-pointer r)
                   (register-finalizer r (lambda (r) (free f)))

Beware, though, that a 'raw object shouldn't refer to GCable objects,
since 'raw memory is not traversed by the GC. Refering to other 'raw
objects is no problem, of course, and 'raw is always fine for atomic
data (which is the intent in the example above, I think).

Movement of GCable objects is the main challenge for connecting 3m with
foreign libraries.

The only other potential issue is when a record contains a mixture of
pointers and non-pointers; in that case, simply using 'nonatomic is
enough with CGC, but 3m needs a more precise specification for
traversing the object. So far, I haven't seen a use of "foreign.ss"
where this difference is an issue.


Posted on the users mailing list.