lua-users home
lua-l archive

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


Wow - that really helps, thanks very much!  That's exactly what I need.

On May 21, 2006, at 6:06 PM, Daniel Collins wrote:

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