获取存储在C中的Lua函数的“指针”

时间:2014-05-22 04:35:36

标签: lua lua-api

在Lua C API中,我可以使用lua_tostring()存储堆栈中的数字或字符串。

如何通过Lua API将Lua函数的“引用”(如果这是正确的术语)传递给C?因此,可以稍后使用lua_call()从C调用它,而不必通过其名称引用它。

(确实需要这样,C程序将来会在某个地方调用该函数,程序对该函数一无所知,因为要传递的函数是在Lua程序中定义的)

1 个答案:

答案 0 :(得分:3)

在C中你不能直接引用Lua函数,但你可以表示数字和字符串。因此,对于以后调用的函数",您可以将此函数存储在某个表中,并通过表的数字或字符串键引用它。

这是一个简单明了的机制:

在Lua方面:

funcs = {}

local function register_hanlder(key, fn)
  funcs[key] = fn
end

register_handler("on_mouse_click", function()
  print "You clicked me!"
end)

在C方面:

/* code not tested */
lua_getglobal(L, "funcs");
lua_getfield(L, -1, "on_mouse_click");
if (!lua_isnil(L, -1)) {
  lua_call(L, 0, 0);
else {
  // nothing registered
}

您可以在注册表中注册它们,而不是在全局表中注册这些函数(请参阅luaL_ref)。您将获得一些整数(这是函数值所在的注册表表中的键),您可以在C代码中传递它。

请注意,如果您不需要存储Lua功能,请稍后再使用"你不需要这些:如果你的C函数有一些Lua函数通过参数传递给它,你可以直接调用它。

==编辑:

正如我所提到的,您可以在"注册表"中存储对函数的引用,而不是使用全局变量(上面的funcs)。从概念上讲,这种方法与前一种方法没有区别。

让我们重复使用上一个示例:您希望Lua程序员能够注册一个在应用程序中单击鼠标时将被触发的函数。

Lua方面看起来像这样:

register_mouse_click_handler(function()
  print "the mouse was clicked!"
end)

在C方面,您可以定义register_mouse_click_handler

static int the_mouse_click_handler = 0;

static int register_mouse_click_handler(lua_State* L) {
  the_mouse_click_handler = luaL_ref(L, LUA_REGISTRYINDEX);
  return 0;
}

(......并将其暴露给Lua。)

然后,在您的应用程序中,当单击鼠标并且您想要调用Lua函数时,您会执行以下操作:

...
if (the_mouse_click_handler != 0) {
  lua_rawgeti(L, LUA_REGISTRYINDEX, the_mouse_click_handler);
  lua_call(L, 0, 0);
} else {
  // No mouse handler was registered.
}
...

(我可能在代码中有拼写错误。)