[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: storing a lua closure in a C object, then calling it from C?
- From: "Daniel Collins" <daniel.collins@...>
- Date: Mon, 22 May 2006 10:36:46 +0930
> What calls do you use to grab the function and push it into the
> table? lua_tothread() and lua_pushthread() ? I can't see any other
> API functions to grab a Lua function from the stack, or place one on
> the stack...
> Or do you use lua_rawget() and lua_setfield() ?
For the lua functions, they never leave the stack. I get the callback as
a parameter on the stack at a known index. I then use lua_pushvalue to
get that function to top of the stack before using luasettable to store
it in my callback table. For the C callback functions I use
lua_pushcfunction. I also use lua_isfunction to verify that the callback
function is where it should be when the factory method starts up. The
relevant code to looks like this:
if (lua_isfunction(L, nCallbackFnIndex))
{
// this function just retrieves the table from the registry and
leaves it on the stack
GetRegistryTable(L, CALLBACK_TABLE_REGISTRY_INDEX);
lua_pushlightuserdata(L, pWidget); // this is the key
lua_pushvalue(L, nCallbackFnIndex); // this is the data
lua_settable(L, -3);
lua_pop(L, 1); // finished with the callback table
}
The test is there because the callback functions are optional in my
system. The factory method generates an error if the callback is neither
a function or nil.
For what its worth, my function calling code is somewhat similar. It is
a lua C function so it gets all parameters on the stack:
int DispatchCallback(lua_State* L)
{
// 1 should be the pMenu lightuserdata
// 2 should be the pWidget lightuserdata
// 3 should be the event type
// validity checking snipped
GetRegistryTable(L, CALLBACK_TABLE_REGISTRY_INDEX);
lua_pushvalue(L, 2); /* get the pWidget key onto the top of the stack
*/
lua_gettable(L, -2); /* the callback table is now at -2 */
lua_remove(L, -2); /* finished with the callback table */
// now the top of the stack should either be a function or nil,
// depending on if this widget registered a callback
if (lua_isnil(L, -1))
{
// callback not supplied. Nothing to do
return 0;
}
else
if (lua_isfunction(L, -1))
{
// if we are calling a C function,
// then the first parameter is the C pointer to the widget
// Lua functions get the userdata instead.
if (lua_iscfunction(L, -1))
{
lua_pushvalue(L, 2);
}
else
{
// get the userdata from the widget table
GetRegistryTable(L, WIDGET_TABLE);
lua_pushvalue(L, 2); // lightuserdata key to widget
table
lua_gettable(L, -2); // retrieve the userdata
lua_remove(L, -2); // remove the table from the
stack
// Now the top of the stack should be the userdata
if (!lua_isuserdata(L, -1))
{
return luaL_error(L, "DispatchCallback: userdata
is missing from widget table");
}
}
lua_pushvalue(L, 3); // push the event type onto the top of
the stack.
lua_call(L, 2, 0);
}
return 0;
}
Hope that helps. Since you need to iterate the entire table and call
everything you will end up with something different.
- DC