【问题标题】:Setting userdata as namespace in Lua在 Lua 中将 userdata 设置为命名空间
【发布时间】:2013-11-22 23:56:08
【问题描述】:

我已经研究过这个主题并尝试了各种方法,但我无法实现我的想法(我什至不确定这是否可能)。基本上,我有几个用 C 语言创建的 userdata 对象,可以通过它们的元表访问,如下所示:

Main.lua

config.display_width = 1280

我想做的是将配置命名空间“强制”到特定脚本。您已经猜到了,我需要保护一个配置文件,以便限制用户处理配置元表。像这样:

Config.lua

display_width = 1280

而且我知道我必须在 C 中做这样的事情:

// Register the config metatable and its methods
luaL_loadfile(L, "my_config.cfg");
lua_getglobal(L, "config"); // Is this necessary?
lua_setfenv(L, -2); // I know this has to be used, but how?
lua_pcall(L, 0, 0, 0);

提前谢谢你,这个快把我逼疯了!

PS:为了记录,我真的需要保持配置用户数据原样,因为它绑定到 C 结构。因此,我不担心在不同环境之间“丢失” Lua 状态或声明的变量。

添加以下信息。这就是配置用户数据的创建方式:

const struct luaL_Reg metaconfig[] =
{
    {"__index", l_get},
    {"__newindex", l_set},
    {NULL, NULL}
};

lua_newuserdata(L, sizeof(void *));

luaL_newmetatable(L, "metaconfig");
luaL_register(L, NULL, metaconfig);
lua_setmetatable(L, -2);

lua_setglobal(L, "config");

因此,每次用户从配置用户数据中设置或获取值时,我都会通过 __index__newindex 方法更新 C 结构。

【问题讨论】:

    标签: c namespaces lua environment lua-userdata


    【解决方案1】:

    你并不需要一个代表配置表的全局变量,你也可以使用 lua_ref。

    这里按预期工作(我猜):

    #include <lua.h>
    #include <lauxlib.h>
    #include <stdlib.h>
    
    int main (void){
        int idxConfig, res;
        lua_State *L = luaL_newstate();
        if ((res = luaL_loadfile(L,"my_config.cfg")) != 0){//Load file
            printf("Got error code %d loading file my_config.cfg, exiting",res);
            exit(-1);
        }
        lua_newtable(L); // new config table
        lua_pushvalue(L,-1);// duplicate table
        idxConfig = lua_ref(L,LUA_REGISTRYINDEX); // take a reference to the table (pops it)
        lua_setfenv(L,-2); // pop table, set as environment for loaded chunk
        lua_call(L,0,0); // load config -- nothing on stack
        lua_rawgeti(L,LUA_REGISTRYINDEX,idxConfig); //push config table
        lua_getfield(L,1,"display"); //read out "display"
        lua_Integer disp_width = lua_tointeger(L,-1);
        printf("Display width = %d",(int) disp_width);
        lua_close(L);
        exit(0);
    }
    

    【讨论】:

    • 对不起,恐怕不是这样。请记住,我已经拥有创建了配置用户数据。因此,每次用户在现实中设置或获取配置字段时,我都会在我自己的 C 结构之间交换数据。
    • 实际上,我可以使用您的解决方案,但我不得不遍历调用 my_config.cfg 的结果表。这不是我的想法(正如我在编辑中解释的那样),但我想如果没有更好的建议可以做到。谢谢!
    • 但是等等,配置的东西是一个简单的表,不是吗?因为你一直称它为“用户数据”。在我的示例中,我只使用了一个新表,您将从注册表或您正在使用的 lua_State 的全局表中获取配置表,不是吗?
    • 不,就是这样;请参阅我在上面发布的新代码。 Config 是一个带有 metatable 和 all 的 userdata。因此,每次用户访问配置时,都会在 C 中触发 __index 和 __newindex。
    • AFAIK 无法将用户数据设置为 Lua 中的环境。参考总是说“桌子”。所以,我想问题是:你真的想直接使用这个 userdatum 还是只 setfenv 一个表作为块,并在调用它后读出它的内容会更容易?
    猜你喜欢
    • 2014-12-31
    • 1970-01-01
    • 2023-03-29
    • 2015-10-01
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 2018-03-11
    • 2012-11-05
    相关资源
    最近更新 更多