<div dir="ltr"><div><div><div><div><div><div><div><div>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<br>
- no copying was necessary, and<br></div>- the original structure wouldn't be released as long as derived references existed.<br><br></div><div>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.<br>
</div><div><br></div>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:<br><br>
<a href="https://github.com/euccastro/gambit-SDL2/blob/master/ffi-macro.scm">https://github.com/euccastro/gambit-SDL2/blob/master/ffi-macro.scm</a><br></div>(find struct-or-union-type)<br><br></div><div>Usage examples:<br>
<a href="https://github.com/euccastro/gambit-SDL2/blob/master/test-ffi.scm">https://github.com/euccastro/gambit-SDL2/blob/master/test-ffi.scm</a><br><a href="https://github.com/euccastro/gambit-SDL2/blob/master/sdl.scm">https://github.com/euccastro/gambit-SDL2/blob/master/sdl.scm</a><br>
</div><div>(see SDL_Event. |voidstar| is how we tell the macro that we want it to manage this as described above)<br></div><div><br></div>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.<br>
<br></div>I'm also factoring that more nicely so the parts are easier to read and test separately.<br><br></div>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.<br>
<br>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.<br><br></div>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.<br>
<br></div>Thanks for reading and have some happy scheming!<br></div>