diff --git a/src/framework/luaengine/luaobject.h b/src/framework/luaengine/luaobject.h index 9c1e3b71..41ce637e 100644 --- a/src/framework/luaengine/luaobject.h +++ b/src/framework/luaengine/luaobject.h @@ -33,6 +33,9 @@ public: LuaObject(); virtual ~LuaObject(); + template + void connectLuaField(const std::string& field, const std::function& f, bool pushFront = false); + /// Calls a function or table of functions stored in a lua field, results are pushed onto the stack, /// if any lua error occurs, it will be reported to stdout and return 0 results /// @return the number of results @@ -85,8 +88,66 @@ private: int m_fieldsTableRef; }; +template +void connect(const LuaObjectPtr& obj, const std::string& field, const std::function& f, bool pushFront = false); + +template +typename std::enable_if::value, void>::type +connect(const LuaObjectPtr& obj, const std::string& field, const Lambda& f, bool pushFront = false); + #include "luainterface.h" +template +void LuaObject::connectLuaField(const std::string& field, const std::function& f, bool pushFront) +{ + luaGetField(field); + if(g_lua.isTable()) { + if(pushFront) + g_lua.pushInteger(1); + push_luavalue(f); + g_lua.callGlobalField("table","insert"); + } else { + if(g_lua.isNil()) { + push_luavalue(f); + luaSetField(field); + g_lua.pop(); + } else if(g_lua.isFunction()) { + g_lua.newTable(); + g_lua.insert(-2); + g_lua.rawSeti(1); + push_luavalue(f); + g_lua.rawSeti(2); + luaSetField(field); + } + } +} + +// connect for std::function +template +void connect(const LuaObjectPtr& obj, const std::string& field, const std::function& f, bool pushFront) { + obj->connectLuaField(field, f, pushFront); +} + +namespace luabinder { + template + struct connect_lambda; + + template + struct connect_lambda { + static void call(const LuaObjectPtr& obj, const std::string& field, const Lambda& f, bool pushFront) { + connect(obj, field, std::function(f), pushFront); + } + }; +}; + +// connect for lambdas +template +typename std::enable_if::value, void>::type +connect(const LuaObjectPtr& obj, const std::string& field, const Lambda& f, bool pushFront) { + typedef decltype(&Lambda::operator()) F; + luabinder::connect_lambda::call(obj, field, f, pushFront); +} + template int LuaObject::luaCallField(const std::string& field, const T&... args) { // note that the field must be retrieved from this object lua value