2016-07-02 67 views
2

一个简单的生成示例。Lua从参数中获取函数

protocol.onConnect(function() end, function() end, ...) 

现在在c中,我想要得到在参数#1,#2中的函数。
在字符串,数字......我们可以使用它们(lua_getstring,..),但我至少没有找到如何获得函数。

int luaProtocolOnConnect(lua_State* L) 
{ 
    int base_func // funC#1 
    int call_func // funC#2 
    .... 
} 

回答

3

你不能真正“获得”一个Lua函数。 Lua函数,如Lua表,是纯粹的Lua对象。因此,他们没有C或C++模拟器。如果你想调用一个Lua函数,那是通过lua_call,lua_pcall或类似的函数完成的。这是在Lua栈上原位完成的。

所以你不能把一个Lua函数变成一个C++值。 可以做什么是采取一个Lua函数和操纵它的各种方式,所有的Lua对象可以被操纵。

例如,假设您想要将一个Lua函数存储在一个C++对象中,然后再调用其中存储的Lua函数。显然,你不能直接将Lua函数转换为C++值。 可以做的是将Lua函数存放在C++可以访问的地方。你使用有一个C++类似的值来存储Lua函数。对于您想要存储的每个对象,此值必须是唯一的。存储对象时获得的值将保存在C++对象中。当需要检索Lua函数时,只需使用存储的值来检索它。

因为这是一个非常普遍的操作,Lua有方法来促进这一点。首先是Lua注册表,一个C++可以访问的表格,但Lua代码不能(除非您授予它访问权限)。

第二个是luaL_ref系列功能。 luaL_ref将堆栈顶部的任何内容都粘贴到您提供的表格中,并返回给您一个整数键,以便稍后使用它来检索它。 lua_rawgeti可用于通过密钥从表中检索函数,luaL_unref接受表和整数键,当您完成该操作时,从表中删除引用的函数。

所以,如果你想存储这样的功能,你只需要创建一个这样的表,将其粘贴在注册表中的一个已知位置(以便您可以随时获取它),然后使用luaL_ref来存储这些功能。当它们打电话给他们时,用lua_rawgeti检索它们。当你完成使用它们时,用luaL_unref销毁它们。

3

您可以使用lua_isfunction来检查它是否是一个函数,使用​​推动在堆栈的顶部的值,然后使用luaL_refluaL_ref(L,LUA_REGISTRYINDEX);),把它变成一个独特的密钥可以在以后参考检索值(lua_rawgeti(L,LUA_REGISTRYINDEX,ref))并调用该函数。

+0

将事情直接引用到注册表中可能不是一个好主意。除非您的代码是将在该Lua环境中执行的唯一C/C++代码。 –

+0

我一般同意,但在这种情况下,关键是保证是唯一的,我见过一些图书馆没有问题(例如,winapi)。 OP可根据需要替换他们自己的表格。 –

+0

它只保证是唯一的“只要你不手动添加整数键到表't'”。 –