我正在尝试使用C API在Lua中包装ncurses。我正在使用stdscr
指针:在调用initscr
之前这是NULL,并且通过设计我的绑定从Lua调用initscr
。所以在驱动程序函数中我这样做:
// Driver function
LUALIB_API int luaopen_liblncurses(lua_State* L){
luaL_newlib(L, lncurseslib);
// This will start off as NULL
lua_pushlightuserdata(L, stdscr);
lua_setfield(L, -2, "stdscr");
lua_pushstring(L, VERSION);
lua_setglobal(L, "_LNCURSES_VERSION");
return 1;
}
这是按预期工作的。当我需要修改stdscr
时出现问题。 initscr
受此限制:
/*
** Put the terminal in curses mode
*/
static int lncurses_initscr(lua_State* L){
initscr();
return 0;
}
我需要将库中的stdscr
设置为不再为空。 Lua方面的示例代码:
lncurses = require("liblncurses");
lncurses.initscr();
lncurses.keypad(lncurses.stdscr, true);
lncurses.getch();
lncurses.endwin();
但是,lncurses.stdscr
为NULL,因此它实际上运行的是等效于keypad(NULL, true);
我的问题是,如何在创建库后修改Lua中的库值?
答案 0 :(得分:1)
您可以使用registry。
Lua提供了一个注册表,一个预定义的表,任何C代码都可以使用它来存储它需要存储的任何Lua值。注册表始终位于伪索引
LUA_REGISTRYINDEX
。任何C库都可以将数据存储到此表中,但必须注意选择与其他库使用的键不同的键,以避免冲突。通常,您应该使用包含您的库名称的字符串作为键,或者使用代码中具有C对象地址的轻用户数据,或者您的代码创建的任何Lua对象。与变量名一样,以下划线后跟大写字母开头的字符串键保留给Lua。
创建时在注册表中存储对模块表的引用。
LUALIB_API int luaopen_liblncurses(lua_State* L) {
luaL_newlib(L, lncurseslib);
// This will start off as NULL
lua_pushlightuserdata(L, stdscr);
lua_setfield(L, -2, "stdscr");
lua_pushstring(L, VERSION);
lua_setglobal(L, "_LNCURSES_VERSION");
// Create a reference to the module table in the registry
lua_pushvalue(L, -1);
lua_setfield(L, LUA_REGISTRYINDEX, "lncurses");
return 1;
}
然后当你initscr
时,更新字段。
static int lncurses_initscr(lua_State* L) {
initscr();
// Update "stdscr" in the module table
lua_getfield(L, LUA_REGISTRYINDEX, "lncurses");
lua_pushlightuserdata(L, stdscr);
lua_setfield(L, -2, "stdscr");
return 0;
}