lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


It is not quite the same situation but the UI system I have been
developing this last week does something similar. 

In my C code I first create two lua tables: one for storing callback
functions and the other for storing the full userdata.

When the lua code calls a factory method to create a new widget my C
factory function ends up with 3 essential items - the C object that
represents the UI widget in the C API, the full userdata representing
the widget for lua, and on the stack there is a lua function that was
passed as a parameter to the factory method. I add the callback function
to its table and the userdata to its table using the C object pointer
(pushed as lightuserdata) as the key in both cases.

Then when my C API triggers a UI event for one of the widgets, I get a
function call with a pointer to the C object. This then looks up the
function (or closure) and puts it on the stack. Second it looks up the
fulluserdata, puts it on the stack then does a lua_call (this is already
running in protected mode so I don't need a pcall). This works really
well. Passing the fulluserdata as the first parameter means the callback
is compatible with lua methods (eg: function m:callback()).

This is also similar to your case since the actual widgets are allocated
outside of lua. The fulluserdata just holds the C pointer. The fact that
I am holding the fulluserdata in a lua table prevents any garbage
collection.

Since my UI system also has a C API for creating widgets, it also has a
pathway for storing cfunctions in the callback table. In this case the
callback function receives the C pointer rather than the fulluserdata as
the only parameter.

I could also have used a single table, keyed by the C pointer with each
entry being another table holding the callback function and the
fulluserdata but I don't see how this would be any different for my
usage pattern. Perhaps if I was updating all the objects.

The fact that some of the registered functions have upvalues and others
don't is all handled transparently since I am using lua tables and API
calls to handle all the data.

- DC