From 5ce610659adea3159549d4863c2479163fce89f4 Mon Sep 17 00:00:00 2001 From: Nicolas Noble Date: Wed, 31 Jul 2013 11:31:38 -0700 Subject: Even further changes in the Lua class binding system. Simplifying the callback system by using the Lua's C closure mechanism. --- includes/BLua.h | 164 ++++++++++++++++++++++++++++++------------------------ src/BLua.cc | 26 ++++++--- tests/test-Lua.cc | 15 +---- 3 files changed, 114 insertions(+), 91 deletions(-) diff --git a/includes/BLua.h b/includes/BLua.h index 6db642e..8f0993f 100644 --- a/includes/BLua.h +++ b/includes/BLua.h @@ -47,8 +47,22 @@ class LuaObjectFactory { virtual void pushObjectAndMembers(Lua & L) = 0; template void pushObj(Lua & L, T * obj, const char * name = NULL); - static void pushIt(Lua & L, const char * name, lua_CFunction func); - static void pushMeta(Lua & L, const char * name, lua_CFunction func); + static void pushMethod(Lua & L, const String & name, lua_CFunction func, int upvalues = 0) { + pushMethod(L, name.to_charp(), name.strlen(), func, upvalues); + } + static void pushMeta(Lua & L, const String & name, lua_CFunction func, int upvalues = 0) { + pushMeta(L, name.to_charp(), name.strlen(), func, upvalues); + } + template + static void pushMethod(Lua & L, const char (&str)[S], lua_CFunction func, int upvalues = 0) { + pushMethod(L, str, S - 1, func, upvalues); + } + template + static void pushMeta(Lua & L, const char (&str)[S], lua_CFunction func, int upvalues = 0) { + pushMeta(L, str, S - 1, func, upvalues); + } + static void pushMethod(Lua & L, const char * name, int strSize, lua_CFunction func, int upvalues = 0); + static void pushMeta(Lua & L, const char * name, int strSize, lua_CFunction func, int upvalues = 0); static LuaObjectBase * getMeInternal(Lua & L, int idx); friend class Lua; private: @@ -95,6 +109,8 @@ class Lua { void push(lua_Number n) { checkstack(); lua_pushnumber(L, n); } void push(const String & s) { checkstack(); lua_pushlstring(L, s.to_charp(), s.strlen()); } void push(bool b) { checkstack(); lua_pushboolean(L, b); } + template + void push(const char (&str)[S]) { checkstack(); lua_pushlstring(L, str, S - 1); } void push(const char * str, int size = -1) { if (size < 0) size = strlen(str); checkstack(); lua_pushlstring(L, str, size); } void push(void * p) { checkstack(); lua_pushlightuserdata(L, p); } void push(lua_CFunction f, int n = 0) { checkstack(); lua_pushcclosure(L, f, n); } @@ -131,6 +147,8 @@ class Lua { bool islightuserdata(int i = -1) { return lua_islightuserdata(L, i); } bool isobject(int i = -1); + int upvalue(int i) { return lua_upvalueindex(i); } + bool toboolean(int i = -1) { return lua_toboolean(L, i); } lua_Number tonumber(int i = -1) { return lua_tonumber(L, i); } String tostring(int i = -1); @@ -213,58 +231,8 @@ struct lua_functypes_t { int argtypes[MAXARGS]; }; -#define DECLARE_METHOD(classname, enumvar) static int method_##enumvar(lua_State * L) { \ - return LuaHelpers::method_multiplex( \ - enumvar, \ - L, \ - sLua_##classname::classname##_proceed, \ - NULL, \ - classname##_methods, \ - true); \ - } - -#define DECLARE_CONSTRUCTOR(classname, enumvar) static int constructor(lua_State * L) { \ - return LuaHelpers::method_multiplex( \ - enumvar, \ - L, \ - NULL, \ - sLua_##classname::classname##_proceed_statics, \ - classname##_functions, \ - false); \ - } - -#define DECLARE_FUNCTION(classname, enumvar) static int function_##enumvar(lua_State * L) { \ - return LuaHelpers::method_multiplex( \ - enumvar, \ - L, \ - NULL, \ - sLua_##classname::classname##_proceed_statics, \ - classname##_functions, \ - false); \ - } - -#define DECLARE_STATIC(classname, enumvar) static int static_##enumvar(lua_State * L) { \ - return LuaHelpers::method_multiplex( \ - enumvar, \ - L, \ - NULL, \ - sLua_##classname::classname##_proceed_statics, \ - classname##_functions, \ - false); \ - } - -#define PUSH_METHOD(classname, enumvar) pushIt( \ - L, \ - classname##_methods[enumvar].name, \ - sLua_##classname::method_##enumvar) - -#define PUSH_METAMETHOD(classname, enumvar) pushMeta( \ - L, \ - String("__") + classname##_methods[enumvar].name, \ - sLua_##classname::method_##enumvar) - #define PUSH_CLASS(classname) \ - bool classPushed = true; \ + bool callPushClassFirst = true; \ { \ L.newtable(); \ L.push("name"); \ @@ -276,7 +244,7 @@ struct lua_functypes_t { } #define PUSH_SUBCLASS(classname, parentname) \ - bool classPushed = true; \ + bool callPushClassFirst = true; \ { \ L.newtable(); \ L.push("name"); \ @@ -290,24 +258,62 @@ struct lua_functypes_t { L.settable(); \ } -#define PUSH_CONSTRUCTOR(classname, enumvar) L.declareFunc("new", sLua_##classname::constructor, -1) +#define PUSH_METHOD(classname, enumvar) { \ + L.push(String(classname##_methods[enumvar].name)); \ + L.push((lua_Number) enumvar); \ + L.push((void *) sLua_##classname::classname##_proceed); \ + L.push((void *) NULL); \ + L.push((void *) classname##_methods); \ + L.push(true); \ + L.push(LuaHelpers::method_multiplex_closure, 5); \ + L.settable(); \ +} -#define PUSH_STATIC(classname, enumvar) { \ - AAssert(classPushed, "Please call PUSH_(SUB)CLASS first"); \ - L.declareFunc( \ - classname##_functions[enumvar].name, \ - sLua_##classname::static_##enumvar, \ - -1); \ +#define PUSH_METAMETHOD(classname, enumvar) { \ + L.push(String("__") + classname##_methods[enumvar].name); \ + L.push((lua_Number) enumvar); \ + L.push((void *) sLua_##classname::classname##_proceed); \ + L.push((void *) NULL); \ + L.push((void *) classname##_methods); \ + L.push(true); \ + L.push(LuaHelpers::method_multiplex_closure, 5); \ + L.settable(); \ } -#define PUSH_FUNCTION(classname, enumvar) L.declareFunc( \ - classname##_functions[enumvar].name, \ - sLua_##classname::function_##enumvar) +#define PUSH_CONSTRUCTOR(classname, enumvar) { \ + callPushClassFirst = true; \ + L.push("new"); \ + L.push((lua_Number) enumvar); \ + L.push((void *) NULL); \ + L.push((void *) sLua_##classname::classname##_proceed_static); \ + L.push((void *) classname##_functions); \ + L.push(false); \ + L.push(LuaHelpers::method_multiplex_closure, 5); \ + L.settable(); \ +} -#define PUSH_SUBFUNCTION(classname, enumvar, array) L.declareFunc( \ - classname##_functions[enumvar].name, \ - sLua_##classname::function_##enumvar, \ - array) +#define PUSH_STATIC(classname, enumvar) { \ + callPushClassFirst = true; \ + L.push(classname##_functions[enumvar].name); \ + L.push((lua_Number) enumvar); \ + L.push((void *) NULL); \ + L.push((void *) sLua_##classname::classname##_proceed_static); \ + L.push((void *) classname##_functions); \ + L.push(false); \ + L.push(LuaHelpers::method_multiplex_closure, 5); \ + L.settable(); \ +} + +#define PUSH_FUNCTION(classname, enumvar) { \ + L.push(classname##_functions[enumvar].name); \ + L.push((lua_Number) enumvar); \ + L.push((void *) NULL); \ + L.push((void *) sLua_##classname::classname##_proceed_static); \ + L.push((void *) classname##_functions); \ + L.push(false); \ + L.push(LuaHelpers::method_multiplex_closure, 5); \ + L.settable(LUA_GLOBALSINDEX); \ +} #define PUSH_CLASS_DONE() L.pop() @@ -347,14 +353,28 @@ class LuaHelpersBase { template class LuaHelpers : public LuaHelpersBase { + typedef int (*proceed_t)(Lua & L, int n, T * obj, int caller); + typedef int (*proceed_static_t)(Lua & L, int n, int caller); public: - static int method_multiplex(int caller, lua_State * __L, int (*proceed)(Lua & L, int n, T * obj, int caller), int (*proceed_static)(Lua & L, int n, int caller), lua_functypes_t * tab, bool method) { + static int method_multiplex_closure(lua_State * __L) { Lua L(__L); + int caller; + proceed_t proceed; + proceed_static_t proceed_static; + lua_functypes_t * tab; + bool method; + + caller = L.tonumber(L.upvalue(1)); + proceed = (proceed_t) L.touserdata(L.upvalue(2)); + proceed_static = (proceed_static_t) L.touserdata(L.upvalue(3)); + tab = (lua_functypes_t *) L.touserdata(L.upvalue(4)); + method = L.toboolean(L.upvalue(5)); + return method_multiplex(caller, L, proceed, proceed_static, tab, method); } private: - static int method_multiplex(int caller, Lua & L, int (*proceed)(Lua & L, int n, T * obj, int caller), int (*proceed_static)(Lua & L, int n, int caller), lua_functypes_t * tab, bool method) { + static int method_multiplex(int caller, Lua & L, proceed_t proceed, proceed_static_t proceed_static, lua_functypes_t * tab, bool method) { int r; try { @@ -368,7 +388,7 @@ class LuaHelpers : public LuaHelpersBase { return r; } - static int method_multiplex_resume(int caller, Lua & L, int (*proceed)(Lua & L, int n, T * obj, int caller), int (*proceed_static)(Lua & L, int n, int caller), lua_functypes_t * tab, bool method) { + static int method_multiplex_resume(int caller, Lua & L, proceed_t proceed, proceed_static_t proceed_static, lua_functypes_t * tab, bool method) { int r; try { @@ -382,7 +402,7 @@ class LuaHelpers : public LuaHelpersBase { return r; } - static int method_multiplex_internal(int caller, Lua & L, int (*proceed)(Lua & L, int n, T * obj, int caller), int (*proceed_static)(Lua & L, int n, int caller), lua_functypes_t * tab, bool method) { + static int method_multiplex_internal(int caller, Lua & L, proceed_t proceed, proceed_static_t proceed_static, lua_functypes_t * tab, bool method) { int add = method ? 1 : 0; int n = L.gettop() - add; T * obj = 0; diff --git a/src/BLua.cc b/src/BLua.cc index 48a3305..5bbdd07 100644 --- a/src/BLua.cc +++ b/src/BLua.cc @@ -804,7 +804,7 @@ void Balau::LuaObjectFactory::pushMe(Lua & L, LuaObjectBase * o, const char * ob L.push(objname); L.settable(-3, true); } - pushIt(L, "destroy", LuaStatics::destructor); + pushMethod(L, "destroy", LuaStatics::destructor); if (!m_wantsDestruct) o->detach(); } @@ -827,17 +827,29 @@ Balau::LuaObjectBase * Balau::LuaObjectFactory::getMeInternal(Lua & L, int i) { return o; } -void Balau::LuaObjectFactory::pushIt(Lua & L, const char * s, lua_CFunction f) { - L.push(s); - L.push(f); +void Balau::LuaObjectFactory::pushMethod(Lua & L, const char * s, int strSize, lua_CFunction f, int upvalues) { + if (upvalues == 0) { + L.push(s, strSize); + L.push(f); + } else { + L.push(f, upvalues); + L.push(s, strSize); + L.insert(-2); + } L.settable(-3, true); } -void Balau::LuaObjectFactory::pushMeta(Lua & L, const char * s, lua_CFunction f) { +void Balau::LuaObjectFactory::pushMeta(Lua & L, const char * s, int strSize, lua_CFunction f, int upvalues) { if (!L.getmetatable()) L.newtable(); - L.push(s); - L.push(f); + if (upvalues == 0) { + L.push(s); + L.push(f); + } else { + L.push(f, upvalues); + L.push(s, strSize); + L.insert(-2); + } L.settable(); L.setmetatable(); } diff --git a/tests/test-Lua.cc b/tests/test-Lua.cc index fec6f11..d4c3637 100644 --- a/tests/test-Lua.cc +++ b/tests/test-Lua.cc @@ -44,18 +44,9 @@ struct lua_functypes_t ObjectTest_functions[] = { { -1, 0, 0, 0, 0 }, }; -class sLua_ObjectTest { - public: - DECLARE_METHOD(ObjectTest, OBJECTTEST_SOMEMETHOD1); - DECLARE_METHOD(ObjectTest, OBJECTTEST_SOMEMETHOD2); - - DECLARE_CONSTRUCTOR(ObjectTest, OBJECTTEST_CONSTRUCTOR); - DECLARE_STATIC(ObjectTest, OBJECTTEST_SOMESTATIC); - DECLARE_FUNCTION(ObjectTest, OBJECTTEST_SOMEFUNCTION); - DECLARE_FUNCTION(ObjectTest, OBJECTTEST_YIELDTEST); - private: +struct sLua_ObjectTest { static int ObjectTest_proceed(Lua & L, int n, ObjectTest * obj, int caller); - static int ObjectTest_proceed_statics(Lua & L, int n, int caller) throw (GeneralException); + static int ObjectTest_proceed_static(Lua & L, int n, int caller) throw (GeneralException); }; class LuaObjectTestFactory : public LuaObjectFactory { @@ -99,7 +90,7 @@ int sLua_ObjectTest::ObjectTest_proceed(Lua & L, int n, ObjectTest * obj, int ca Events::Timeout * evt = NULL; -int sLua_ObjectTest::ObjectTest_proceed_statics(Lua & L, int n, int caller) throw (GeneralException) { +int sLua_ObjectTest::ObjectTest_proceed_static(Lua & L, int n, int caller) throw (GeneralException) { int y; switch (caller) { -- cgit v1.2.3