2

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

// 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,所以它本质上是在运行 c 等价于keypad(NULL, true);

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

4

1 回答 1

1

您可以使用注册表

Lua 提供了一个注册表,一个预定义的表,任何 C 代码都可以使用它来存储它需要存储的任何 Lua 值。注册表始终位于 pseudo-index 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-11T00:00:09.760 回答