首页 > 解决方案 > 通过没有大 if/else 块的 Lua 元表公开 C 函数/变量?

问题描述

我想为在 Lua 中可访问的结构实例创建一个全局接口。例如,我将创建一个名为windowas的元表的全局实例main_window,然后我想从 Lua 中执行以下操作:

main_window.color = {1, 2, 3}
main_window.position.x = 64
main_window.show(true)

为了做到这一点,我使用这个答案中的代码作为基础,因为它是我能找到的最接近的东西。我最终得到了这样的 API

lua_create_window_type(L);
lua_expose_window(L, main_window);
lua_setglobal(L, "main_window");

...

static int lua_window_index(lua_State* L)
{ 
    struct window_state** w = luaL_checkudata(L, 1, "window");
    char* index = luaL_checkstring(L, 2);
    if (strcmp(index, "x") == 0) {
        lua_pushnumber(L, (*w)->x);
    } else if (strcmp(index, "show") == 0) {
        lua_pushcfunction(L, lua_window_show);
    } else {
        ...
    }
    return 1; 
}

static int lua_window_newindex(lua_State* L)
{
    struct window_state** w = luaL_checkudata(L, 1, "window");
    char* index = luaL_checkstring(L, 2);
    if (strcmp(index, "x") == 0) {
        (*w)->x = luaL_checkinteger(L, 3);
    } else {
        ...
    }
    return 0;
}

我不可避免地会得到数十或数百个我想要访问的函数和变量。使用此模板,我必须if strcmp == 0 else if为每个模板手动创建一个。我必须复制整个块以允许分配。由于字符串比较的数量,我也不希望在接近末尾的函数调用相对较慢。总的来说,这似乎不是一个“可维护”的解决方案,Lua 的作者也不打算这样做。

当我只需要函数时,我所要做的就是推送一个标准的全局表和我需要的任何函数,但是尝试像本地 Lua 表一样允许直接变量访问会使这变得更加困难(在你问为什么不只使用函数之前,我已经尝试过并且只有从 Lua 访问“getter/setter”函数对我的使用来说是非常痛苦和丑陋的)。

if/else对重复块的更可维护替代方案的建议?

标签: capiif-statementluametatable

解决方案


推荐阅读