在 Lua 注册表中存储 C 结构
Storing a C structure in the Lua registry
当我将 Lua 集成到我的 C 程序中时,我一直在使用指向 C 结构的 static
指针来存储我需要在绑定到的方法中重用的对象Lua 状态。
但是,一旦我将 Lua 库从主程序中分离出来,这就不起作用了,所以我似乎需要使用注册表来存储我的结构。
如何将我的 C 结构指针存储在 Lua 注册表中?
这是我目前正在做的事情:
static augeas *aug = NULL;
static int lua_aug_get(lua_State *L) {
// Use aug to do something here
/* return the number of results */
return 1;
}
struct lua_State *luaopen_augeas(augeas *a) {
lua_State *L = luaL_newstate();
aug = a; // this clearly does not work
luaL_openlibs(L);
// The methods below will need to access the augeas * struct
// so I need to push it to the registry (I guess)
static const luaL_Reg augfuncs[] = {
{ "get", lua_aug_get },
{ "label", lua_aug_label },
{ "set", lua_aug_set },
{ NULL, NULL }
};
luaL_newlib(L, augfuncs);
lua_setglobal(L, "aug");
return L;
}
编辑:根据我在 IRC 上得到的答案,我似乎应该使用 metatable,所以我目前正在研究这个。
我设法使用 Lua 注册表索引并将指针推送为 light userdata:
static const char *Key = "augeas_registry_key"; // The registry key
static augeas *checkaug(lua_State *L) {
lua_pushlightuserdata(L, (void *)&Key); // set the registry key
lua_gettable(L, LUA_REGISTRYINDEX); // retrieve value
augeas *aug = (augeas *)lua_touserdata(L, -1); // cast value
return aug;
}
static int lua_aug_get(lua_State *L) {
augeas *aug = checkaug(L);
// Do stuff with aug
return 1;
}
struct lua_State *luaopen_augeas(augeas *a) {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_pushlightuserdata(L, (void *)&Key); // set registry key
lua_pushlightuserdata(L, (void *)a); // push pointer
lua_settable(L, LUA_REGISTRYINDEX); // push to in registry
static const luaL_Reg augfuncs[] = {
{ "get", lua_aug_get },
{ "label", lua_aug_label },
{ "set", lua_aug_set },
{ NULL, NULL }
};
luaL_newlib(L, augfuncs);
lua_setglobal(L, "aug");
return L;
}
虽然这不是很优雅,但考虑到它使用共享注册表,会话期间加载的其他库可能可以访问它,所以我仍然愿意接受更好的选择。
如果注册表不是足够安全的地方来存储指针,您可以将其作为上值推送到特定函数:
static int lua_aug_get(lua_State *L) {
augeas *aug = lua_touserdata(L, lua_upvalueindex(1));
// Do stuff with aug
return 1;
}
static const luaL_Reg augfuncs[] = {
{ "get", lua_aug_get },
{ "label", lua_aug_label },
{ "set", lua_aug_set },
{ NULL, NULL }
};
lua_createtable(L, 0, 0);
for (size_t i = 0; augfuncs[i].name; i++) {
lua_pushlightuserdata(L, a);
lua_pushcclosure(L, augfuncs[i].func, 1);
lua_setfield(L, -2, augfuncs[i].name);
}
但是存放在注册表中是可以的。它不是脚本可访问的,除了 debug
库,通常不暴露在沙箱中。如果其他图书馆在那里制造自私的混乱,你就有麻烦了。
当我将 Lua 集成到我的 C 程序中时,我一直在使用指向 C 结构的 static
指针来存储我需要在绑定到的方法中重用的对象Lua 状态。
但是,一旦我将 Lua 库从主程序中分离出来,这就不起作用了,所以我似乎需要使用注册表来存储我的结构。
如何将我的 C 结构指针存储在 Lua 注册表中?
这是我目前正在做的事情:
static augeas *aug = NULL;
static int lua_aug_get(lua_State *L) {
// Use aug to do something here
/* return the number of results */
return 1;
}
struct lua_State *luaopen_augeas(augeas *a) {
lua_State *L = luaL_newstate();
aug = a; // this clearly does not work
luaL_openlibs(L);
// The methods below will need to access the augeas * struct
// so I need to push it to the registry (I guess)
static const luaL_Reg augfuncs[] = {
{ "get", lua_aug_get },
{ "label", lua_aug_label },
{ "set", lua_aug_set },
{ NULL, NULL }
};
luaL_newlib(L, augfuncs);
lua_setglobal(L, "aug");
return L;
}
编辑:根据我在 IRC 上得到的答案,我似乎应该使用 metatable,所以我目前正在研究这个。
我设法使用 Lua 注册表索引并将指针推送为 light userdata:
static const char *Key = "augeas_registry_key"; // The registry key
static augeas *checkaug(lua_State *L) {
lua_pushlightuserdata(L, (void *)&Key); // set the registry key
lua_gettable(L, LUA_REGISTRYINDEX); // retrieve value
augeas *aug = (augeas *)lua_touserdata(L, -1); // cast value
return aug;
}
static int lua_aug_get(lua_State *L) {
augeas *aug = checkaug(L);
// Do stuff with aug
return 1;
}
struct lua_State *luaopen_augeas(augeas *a) {
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_pushlightuserdata(L, (void *)&Key); // set registry key
lua_pushlightuserdata(L, (void *)a); // push pointer
lua_settable(L, LUA_REGISTRYINDEX); // push to in registry
static const luaL_Reg augfuncs[] = {
{ "get", lua_aug_get },
{ "label", lua_aug_label },
{ "set", lua_aug_set },
{ NULL, NULL }
};
luaL_newlib(L, augfuncs);
lua_setglobal(L, "aug");
return L;
}
虽然这不是很优雅,但考虑到它使用共享注册表,会话期间加载的其他库可能可以访问它,所以我仍然愿意接受更好的选择。
如果注册表不是足够安全的地方来存储指针,您可以将其作为上值推送到特定函数:
static int lua_aug_get(lua_State *L) {
augeas *aug = lua_touserdata(L, lua_upvalueindex(1));
// Do stuff with aug
return 1;
}
static const luaL_Reg augfuncs[] = {
{ "get", lua_aug_get },
{ "label", lua_aug_label },
{ "set", lua_aug_set },
{ NULL, NULL }
};
lua_createtable(L, 0, 0);
for (size_t i = 0; augfuncs[i].name; i++) {
lua_pushlightuserdata(L, a);
lua_pushcclosure(L, augfuncs[i].func, 1);
lua_setfield(L, -2, augfuncs[i].name);
}
但是存放在注册表中是可以的。它不是脚本可访问的,除了 debug
库,通常不暴露在沙箱中。如果其他图书馆在那里制造自私的混乱,你就有麻烦了。