diff options
| author | jacqueline <me@jacqueline.id.au> | 2023-11-20 13:02:29 +1100 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2023-11-20 13:02:29 +1100 |
| commit | b7f37f6426c78132d338b032962209bd93771039 (patch) | |
| tree | fd9e097ed55167616e630c257a28724b0f1ddc63 /src/lua/property.cpp | |
| parent | b3b512f10e0570f7dc8a04e1613f1234e5532728 (diff) | |
| download | tangara-fw-b7f37f6426c78132d338b032962209bd93771039.tar.gz | |
Add a generic lua function binding, alongside properties
Diffstat (limited to 'src/lua/property.cpp')
| -rw-r--r-- | src/lua/property.cpp | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/src/lua/property.cpp b/src/lua/property.cpp index 3130077b..353e01ae 100644 --- a/src/lua/property.cpp +++ b/src/lua/property.cpp @@ -5,10 +5,12 @@ */ #include "property.hpp" +#include <sys/_stdint.h> #include <memory> #include <string> +#include "lauxlib.h" #include "lua.h" #include "lua.hpp" #include "lvgl.h" @@ -16,11 +18,13 @@ namespace lua { -static const char kMetatableName[] = "property"; +static const char kPropertyMetatable[] = "property"; +static const char kFunctionMetatable[] = "function"; static const char kBindingsTable[] = "bindings"; +static const char kBinderKey[] = "binder"; static auto check_property(lua_State* state) -> Property* { - void* data = luaL_checkudata(state, 1, kMetatableName); + void* data = luaL_checkudata(state, 1, kPropertyMetatable); luaL_argcheck(state, data != NULL, 1, "`property` expected"); return *reinterpret_cast<Property**>(data); } @@ -71,9 +75,25 @@ static const struct luaL_Reg kPropertyBindingFuncs[] = {{"get", property_get}, {"bind", property_bind}, {NULL, NULL}}; +static auto generic_function_cb(lua_State* state) -> int { + lua_pushstring(state, kBinderKey); + lua_gettable(state, LUA_REGISTRYINDEX); + PropertyBindings* binder = + reinterpret_cast<PropertyBindings*>(lua_touserdata(state, -1)); + + size_t* index = + reinterpret_cast<size_t*>(luaL_checkudata(state, 1, kFunctionMetatable)); + const LuaFunction& fn = binder->GetFunction(*index); + return std::invoke(fn, state); +} + PropertyBindings::PropertyBindings(lua_State& s) { + lua_pushstring(&s, kBinderKey); + lua_pushlightuserdata(&s, this); + lua_settable(&s, LUA_REGISTRYINDEX); + // Create the metatable responsible for the Property API. - luaL_newmetatable(&s, kMetatableName); + luaL_newmetatable(&s, kPropertyMetatable); lua_pushliteral(&s, "__index"); lua_pushvalue(&s, -2); @@ -94,16 +114,38 @@ PropertyBindings::PropertyBindings(lua_State& s) { lua_setmetatable(&s, -2); // setmetatable(bindings, meta) lua_settable(&s, LUA_REGISTRYINDEX); // REGISTRY[kBindingsTable] = bindings + + // Create the metatable for C++ functions. + luaL_newmetatable(&s, kFunctionMetatable); + + lua_pushliteral(&s, "__call"); + lua_pushcfunction(&s, generic_function_cb); + lua_settable(&s, -3); // metatable.__call = metatable + + lua_pop(&s, 1); // Clean up the function metatable } auto PropertyBindings::Register(lua_State* s, Property* prop) -> void { Property** data = - reinterpret_cast<Property**>(lua_newuserdata(s, sizeof(Property*))); + reinterpret_cast<Property**>(lua_newuserdata(s, sizeof(uintptr_t))); *data = prop; - luaL_setmetatable(s, kMetatableName); + luaL_setmetatable(s, kPropertyMetatable); } +auto PropertyBindings::Register(lua_State* s, LuaFunction fn) -> void { + size_t* index = reinterpret_cast<size_t*>(lua_newuserdata(s, sizeof(size_t))); + *index = functions_.size(); + functions_.push_back(fn); + + luaL_setmetatable(s, kFunctionMetatable); +} + +auto PropertyBindings::GetFunction(size_t i) -> const LuaFunction& { + assert(i < functions_.size()); + return functions_[i]; +}; + template <class... Ts> inline constexpr bool always_false_v = false; |
