FLI structure problem
I've been tying into a foreign library and getting a crash when looping. I know the foreign library is good, and this is likely just something I'm doing wrong with FLI. I'll try demonstrating this with example code, but if more details are needed to help me solve the issue, I can post those as well. Sorry if this message is a little long, I just want to be sure no detail is left out.The C library has a union of structures, all with the same header. Somewhat like this:
Here is my FLI representation of the above:struct event_header {u32 type;void* pointer;};struct event_type_a {event_header header;u32 data;};struct event_type_b {event_header header;u8 data[16];}// etc…union event {u32 type;event_type_a a;event_type_b b;// ….};
(define-c-struct event-header(type :uint32)(pointer :pointer))(define-c-struct event-type-a(header (:struct event-header))(data :uint32))(define-c-struct event-type-b(header (:struct event-header))(data (:c-array :byte 16)))(define-c-union event(type :uint32)(a (:struct event-type-a))(b (:struct event-type-b)))
Internally, the C code has a queue of events, and I can call the function:
bool get_next_event(event_queue* q, event* output_e);
Now, I didn't want to have to create a foreign event structure for the output. So, I figured that a :reference-return parameter to the FLI function would wok as I would like (and it seems to):
(define-foreign-function (get-next-event "get_next_event")((queue :pointer)(event (:reference-return event))):result-type :boolean)
At this point everything appears to be just fine. I can call the function, get back an event, call #'foreign-slot-value on it and get access to everything as I would expect:
Works great!(multiple-value-bind (pending event)(get-next-event queue)(when pending(case (foreign-slot-value event 'type)))(type-a (print (foreign-slot-value event '(a data))))(type-b …))))
But, if I stick the above code in a loop and just let it spin, eventually (within ~10 seconds) it will crash LispWorks (OS X 32-bit). I don't have to interact, and I don't even have to put events into the queue (pending = nil always). It will just crash.
There was one time when trying things that I got a new window to pop up with details about the crash (which I can't seem to get to happen again), which had a call stack that seemed to imply it was a GC issue. Perhaps I'm doing something wrong above and a GC is attempting to clean up a pointer that's actually still in use and I'm not protecting it?
I've tried wrapping the code above in a #'with-dynamic-foreign-objects macro, but that doesn't appear to help at all. Admittedly, it's starting to become genetic programming at this point.
Any thoughts/suggestions very much appreciated!
Jeff M.