[gambit-list] Anyone else working in a schemey wrapper for c structs/unions/types?

Estevo euccastro at gmail.com
Sun Dec 22 11:00:48 EST 2013


I've experimented in the past with making a macro that would generate the
appropriate ffi code to create and manage c structs/unions/types.  The
challenge was to handle references obtained from accessors to fields
containing other structs/union/types within them in such a way that
- no copying was necessary, and
- the original structure wouldn't be released as long as derived references
existed.

For example, to handle events in SDL you create a SDL_Event union that you
pass to functions to query for events.  When the data for a particular
event is populated, you query the type with evt.type and then access the
fields of the specific type by accessing evt.key, a "view" on the same
structure of type SDL_KeyboardEvent.  There is no point in copying the
structure when you do this.  Also, you don't want the SDL_Event to be
released while you're using (holding a reference to) the
SDL_KeyboardEvent.  While in this case it's not hard to manually keep the
parent object alive, in the general case it feels more schemey to let the
garbage collector take care of that.

What I came up with at that time was not legible and I'm not proud of it.
While it seemed to work in my x64 machine, I got a segmentation fault when
running the tests in a x86 installation:

https://github.com/euccastro/gambit-SDL2/blob/master/ffi-macro.scm
(find struct-or-union-type)

Usage examples:
https://github.com/euccastro/gambit-SDL2/blob/master/test-ffi.scm
https://github.com/euccastro/gambit-SDL2/blob/master/sdl.scm
(see SDL_Event. |voidstar| is how we tell the macro that we want it to
manage this as described above)

The most straightforward way to do it would be to create, in addition to
the macro, a library that maintains a table of weak keys --referring to
derived ("child") structs-- to strong values --referring to the original
("parent") structs.  In the module above I did just that, but I resorted to
dubious tricks to avoid creating that library.  In a new shot at this I'd
just have the library.

I'm also factoring that more nicely so the parts are easier to read and
test separately.

Another plausible approach would be to allocate a zero-size
reference-counted object (with ___alloc_rc(0)), have its data point to the
parent, and make a will with the child's foreign object as testator and
with an action that kills the reference-counted object.  I have tested that
wills still execute after they themselves become unreachable, but I don't
know whether that's behavior I should rely on.  If that is not the case,
then the reference-counted object's data could be a (cons parent-foreign
will), so the will itself will be kept alive until it's executed.

While I had lots of fun looking at the sources and coming up with this, I
suspect the more straightforward table approach involves less overhead.

If anyone else is interested in doing and/or using something like this, I'm
happy to bounce ideas and take suggestions.  I'm working on this mostly on
weekends, but I'll try and be responsive during the week too.

Thanks for reading and have some happy scheming!
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20131222/aeb88951/attachment.htm>


More information about the Gambit-list mailing list