创建后的Lua c API更改库

时间:2017-10-10 18:41:21

标签: c lua lua-api lua-5.2

我正在尝试使用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);

的c

我的问题是,如何在创建库后修改Lua中的库值?

1 个答案:

答案 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;
}