Предоставить функции / переменные C через Lua метатабельно без большого блока if / else? - PullRequest
0 голосов
/ 20 сентября 2018

Я хочу создать глобальный интерфейс для экземпляра структуры, доступного в 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, делает это более трудным (прежде чем вы спросите, почему бы просто не использовать функции, я попробовал, и только наличие доступа к функции «getter / setter» из Lua очень болезненно и уродливо для моих целей).

Предложения по более приемлемым альтернативам дублированным if/else блокам?

...