在Lua中将userdata设置为命名空间

时间:2011-02-15 14:13:45

标签: c namespaces lua environment lua-userdata

我研究了这个主题并尝试了各种方法,但我无法实现我的想法(我甚至不确定它是否可行)。基本上,我在C中创建了几个userdata对象,可以通过它们的metatable访问,如下所示:

Main.lua

config.display_width = 1280

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

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:为了记录,我真的需要保持config userdata,因为它绑定到C结构。因此,我并不担心“失去”Lua状态或在不同环境之间声明变量。

添加以下信息。这就是创建config userdata的方式:

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");

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

1 个答案:

答案 0 :(得分: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);
}