jeudi 20 septembre 2018

Expose C functions/variables via Lua metatable without large if/else block?

I want to create a global interface for a struct instance accessible in Lua. For example, I would create a global instance of a metatable called window as main_window, I would want to then do things like this from Lua:

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

In an attempt to do this, I used the code from this answer as a base since it's the closest thing I could find. I ended up with an API like this

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;
}

I am inevitably going to end up with tens or hundreds of functions and variables I want to be accessible. Using this template I would have to manually create a if strcmp == 0 else if for every single one. I'd have to duplicate the entire block to allow assignment. I also don't want to end up with functions near the end being comparatively slow to call due to the amount of string comparisons. Overall this does not seem like a "maintainable" solution, nor one the Lua authors would have intended.

When I only needed functions all I had to do was push a standard global table and whatever functions I needed, but trying to allow direct variable access like a native Lua table makes this more difficult (before you ask why not just use functions, I've tried and only having "getter/setter" function access from Lua is very painful and ugly for my uses).

Suggestions for more maintainable alternatives to duplicated if/else blocks?

Aucun commentaire:

Enregistrer un commentaire