[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: help with callbacks
- From: "Jérôme Vuarand" <jerome.vuarand@...>
- Date: Sun, 19 Aug 2007 00:26:10 -0400
2007/8/18, Merick <Merick_TeVaran@comcast.net>:
> Jérôme Vuarand wrote:
> > Can you send the prototype of the C function you are calling to
> > register a callback, along with the prototype of that callback ?
>
> function ui_cf Cdecl(Byval L As lua_State Ptr) As Integer
> if lua_gettop(L) <> 8 then return lual_error(L, "[UI.CreateFrame]
> takes 8 args")
> dim ownerbox as UI_BOX_PTR = 0
> dim As integer _
> id = lual_checknumber(L, 2), _
> x = lual_checknumber(L, 3), _
> y = lual_checknumber(L, 4), _
> w = lual_checknumber(L, 5), _
> h = lual_checknumber(L, 6), _
> flags = lual_checknumber(L, 8)
> dim as string func_string = *lual_checkstring(L,7)
> var ret = UI_CreateFrame(ownerbox, id, x, y, w, h,
> @callback_function , flags)
> end function
>
> ----
> In this line of the ui_cf function: var ret =
> UI_CreateFrame(ownerbox, id, x, y, w, h, @callback_function , flags)
> the argument '@callback_function' is the function that I need to create
> that will link to a lua function, but I don't really know where to begin
>
> You can get the library I'm using from this page:
>
> http://www.execulink.com/~coder/freebasic/jmgui.html
It's a Freebasic specific question. It depends if the language handle
closures or not. In C, which do not handle closures, when registering
a callback you usually pass a function pointer and a data pointer. For
example :
typedef void (*callback_t)(void* data);
int register_callback(void* data, callback_t func);
With that kind of API, you have to create a structure to hold the Lua
state pointer and the reference to your Lua closure :
struct callback_t {
lua_State* L;
int index;
};
Your callback will typically take a void* parameter :
void callback(void* data)
{
struct callback_t* cb = data;
lua_State* L = cb->L;
lua_rawgeti(L, LUA_REGISTRYINDEX, cb->index);
lua_call(L, 1, 0);
}
Then in your lua_CFunction you allocate the structure and pass it to
the callback registration function :
int lua__register_callback(lua_State* L)
luaL_checktype(L, 1, LUA_TFUNCTION);
struct callback_t* cb = malloc(sizeof(struct callback_t));
cb->L = L;
lua_pushvalue(L, 1);
cb->index = luaL_ref(L, LUA_REGISTRYINDEX);
register_callback(cb, callback);
}
At some point you will have to free the structure, but that depend on
how callbacks are deregistered.
If the callback registration function doesn't take a data pointer, you
have to store it in a global variable. That's not very clean and will
lead to problem if you have several callbacks at the same time.