From b7f37f6426c78132d338b032962209bd93771039 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Mon, 20 Nov 2023 13:02:29 +1100 Subject: Add a generic lua function binding, alongside properties --- src/lua/property.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 5 deletions(-) (limited to 'src/lua/property.cpp') 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 #include #include +#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(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(lua_touserdata(state, -1)); + + size_t* index = + reinterpret_cast(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(lua_newuserdata(s, sizeof(Property*))); + reinterpret_cast(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(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 inline constexpr bool always_false_v = false; -- cgit v1.2.3