【问题标题】:Lua c API change library after creation创建后Lua c API更改库
【发布时间】:2018-03-22 06:34:47
【问题描述】:

我正在尝试使用 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 中修改库值?

【问题讨论】:

    标签: c lua lua-api lua-5.2


    【解决方案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;
    }
    

    【讨论】:

    • 太棒了!我发现 API 很难学习,但它是有益的。这效果很好。
    • @AlgoRythm 很高兴你发现它很有用。基于堆栈的 API 一开始可能有点棘手,我建议阅读精彩的 Programming in Lua 书。
    • 是的,这已经填满了我过去一周左右的大部分浏览器历史记录!它有很好的记录,对我来说只是一个新概念:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-08
    • 2019-11-07
    • 2012-07-14
    • 2016-05-20
    • 2021-02-25
    • 2010-12-10
    • 2016-10-18
    相关资源
    最近更新 更多