1

我正在尝试为自己创建一个实验环境,在该环境中,我的应用程序作为 telnet 服务器运行,用于理论上无限的 telnet 客户端,这些客户端可以在自己的 Lua 环境中执行 Lua 命令。为此,每个客户端都有自己的线程,因为我希望他们拥有自己的 Windows 消息循环,以满足自己的特定需求。

我创建了几个可在 Lua 中访问的模块来做一些有趣的事情。我还希望能够从 Lua 创建一个窗口,所以我想添加一个名为“window”的模块并添加一个“new”方法。问题是,我需要知道我在哪个线程中(嗯,更具体地说,我需要我用来定义线程正在处理的客户端的类)并且我不知道如何在C Lua 函数用于window.new.

使用普通函数,您可以添加 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(嗯,我想我可以),但必须已经存在更好的方法?

编辑:顺便说一句。我想防止使用全局 Lua 变量来存储指向我的类的指针。这可能会带来安全风险,尽管这个工具可能永远不会在我的计算机之外使用,但我只想正确编码。

4

1 回答 1

2

这些luaopen_*函数应该由 调用require,并且require不传递额外的参数(除了模块名称和文件路径)以避免在具有不同参数的第二次调用返回第一次调用的缓存结果时造成混淆。

LUA_REGISTRYINDEX但是,您可以在创建 Lua 状态后将线程/类存储在注册表中(在伪索引处)。没有debug库,Lua 无法访问注册表,因此您应该是安全的。您可以在luaopen_window函数中检索该类并将其作为方法的上值,或从您的方法中访问注册表。

为避免与在注册表中存储信息的其他模块发生冲突,您可以在代码中使用静态变量的地址作为表键。

于 2014-09-09T10:17:08.020 回答