我正在尝试为自己创建一个实验环境,我的应用程序作为telnet服务器运行,理论上无限制的telnet客户端可以在自己的Lua环境中执行Lua命令。 为此,每个客户端都有自己的线程,因为我希望它们拥有自己的Windows消息循环以满足自己的特定需求。
我已经创建了几个可以在Lua中访问的模块来做一些有趣的事情。我也希望能够从Lua创建一个窗口,所以我想添加一个名为" window"并添加一个" new"方法。问题是,我需要知道我所处的线程(更确切地说,我需要用于定义线程处理的客户端的类)并且我不知道如何获取它在window.new
的C Lua函数中。
使用普通函数,您可以添加upvalues(我已经有一个简单的window
函数,可以创建一个由运行它的线程管理的窗口),但是在创建模块时,这不是当你尝试以标准的方式做到这一点时这么简单。
我的窗口模块具有以下典型的luaopen函数:
LUALIB_API int luaopen_window(lua_State *L)
{
luaL_newmetatable(L, "window");
luaL_setfuncs(L, reg_window_m, 0);
luaL_newlib(L, reg_window_f);
return 1;
}
我的线程创建一个Lua状态并打开必要的库,包括窗口一:
luaL_requiref(L, "window", luaopen_window, 1);
lua_pop(L, 1);
我知道函数luaL_setfuncs
支持upvalues,但它已经太晚了。我没有办法传递值来输入值。
我在调用luaL_requiref
之前尝试推送它们并在luaopen_window
函数中弹出它们,在调用luaL_setfuncs
之前再次推送它们但它不起作用:由于luaL_setfuncs
在内部的工作方式,推送值已经消失。我当然可以编写自己的luaL_setfuncs
来支持upvalues(好吧,我想我可以),但是一定有更好的方法吗?
编辑:BTW。我想阻止使用全局Lua变量来存储指向我的类的指针。这可能会成为一种安全风险,虽然这个工具可能永远不会在我的计算机之外使用,但我只想对此进行编码。
答案 0 :(得分:2)
luaopen_*
函数应该由require
调用,而require
不会传递额外的参数(除了模块名称和文件路径)以避免混淆时使用不同参数的第二次调用返回第一次调用的缓存结果。
但是,您可以在创建Lua状态后将线程/类存储在注册表表中(在伪索引LUA_REGISTRYINDEX
)。没有debug
库,Lua无法访问注册表,因此您应该是安全的。您可以在luaopen_window
函数中检索该类,并将其作为upvalue添加到您的方法中,或者从您的方法中访问注册表。
为避免与在注册表中存储信息的其他模块发生冲突,您可以使用代码中静态变量的地址作为表键。