Lua c API 创建后更改库

我正在使用C API将ncurses包装在Lua中。我正在使用 stdscr 指针:在调用 initscr 之前,这是 NULL,并且通过我的绑定的设计从Lua调用 initscr 。因此,在驱动程序函数中,我做了这个:

// 驱动程序函数
LUALIB_API int luaopen_liblncurses(lua_State* L){
    luaL_newlib(L, lncurseslib);

    // 它将从NULL开始
    lua_pushlightuserdata(L, stdscr);
    lua_setfield(L, -2, "stdscr");

    lua_pushstring(L, VERSION);
    lua_setglobal(L, "_LNCURSES_VERSION");
    return 1;
}

这起到了预期的作用。当我需要修改 stdscr 时,就会出现麻烦。 initscr 绑定如下所示:

/*
** 将终端设置为curses模式
*/
static int lncurses_initscr(lua_State* L){
    initscr();
    return 0;
}

我需要将库中的 stdscr 修改为不再为null。Lua端的示例代码如下:

lncurses = require("liblncurses");
lncurses.initscr();
lncurses.keypad(lncurses.stdscr, true);
lncurses.getch();
lncurses.endwin();

但是, lncurses.stdscr 为 NULL,因此本质上运行C中的 keypad(NULL, true)

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

点赞
用户415823
用户415823

你可以使用 registry

Lua 提供了一个 registry,预定义的表格,可以被任何 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;
}
2017-10-11 00:00:09