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?