如何通过 Lua metatable 公开 C 函数/变量,而不需要大型 if/else 代码块?

我想为在 Lua 中可访问的结构实例创建全局接口。例如,我将创建一个名为 window 的元表的全局实例作为 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 代码块吗?

点赞