From e7db8576b8a4988dfdd206500199e59c3b57bf55 Mon Sep 17 00:00:00 2001 From: Nicolas Noble Date: Tue, 30 Jul 2013 19:10:20 -0700 Subject: Changing things a bit in the Lua binding system. Now pushing a class template means pushing a table by its name, and the constructor is implicit in it. --- includes/BLua.h | 37 +++++++++++++++++++++++++++++++++++++ src/BLua.cc | 2 ++ tests/test-Lua.cc | 29 ++++++++++++++++++++++------- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/includes/BLua.h b/includes/BLua.h index e11c3fb..a6dd2bc 100644 --- a/includes/BLua.h +++ b/includes/BLua.h @@ -223,6 +223,16 @@ struct lua_functypes_t { 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, \ @@ -233,6 +243,16 @@ struct lua_functypes_t { 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, \ @@ -243,6 +263,21 @@ struct lua_functypes_t { String("__") + classname##_methods[enumvar].name, \ sLua_##classname::method_##enumvar) +#define PUSH_CONSTRUCTOR(classname, enumvar) \ + bool constructorPushed = true; \ + L.newtable(); \ + L.push(#classname); \ + L.copy(-2); \ + L.setvar(); \ + L.declareFunc("new", sLua_##classname::constructor, -1) + +#define PUSH_STATIC(classname, enumvar) \ + AAssert(constructorPushed, "Please call PUSH_CONSTRUCTOR first"); \ + L.declareFunc( \ + classname##_functions[enumvar].name, \ + sLua_##classname::static_##enumvar, \ + -1) + #define PUSH_FUNCTION(classname, enumvar) L.declareFunc( \ classname##_functions[enumvar].name, \ sLua_##classname::function_##enumvar) @@ -252,6 +287,8 @@ struct lua_functypes_t { sLua_##classname::function_##enumvar, \ array) +#define PUSH_CLASS_DONE() L.pop() + #define CHECK_METHODS(classname) { \ int i = 0; \ while (classname##_methods[i].number != -1) { \ diff --git a/src/BLua.cc b/src/BLua.cc index 62e4010..cb0e645 100644 --- a/src/BLua.cc +++ b/src/BLua.cc @@ -382,6 +382,8 @@ void Balau::Lua::declareFunc(const char * name, lua_CFunction f, int i) { checkstack(2); lua_pushstring(L, name); lua_pushcfunction(L, f); + if ((i < 0) && (i > LUA_REGISTRYINDEX)) + i += 2; lua_settable(L, i); } diff --git a/tests/test-Lua.cc b/tests/test-Lua.cc index 724369f..1925033 100644 --- a/tests/test-Lua.cc +++ b/tests/test-Lua.cc @@ -15,6 +15,7 @@ class ObjectTest { void someMethod1() { Printer::log(M_DEBUG, "ObjectTest::someMethod1() called on %p.", this); callCount++; } int someMethod2(int p) { Printer::log(M_DEBUG, "ObjectTest::someMethod2() called on %p.", this); callCount++; return p * 2; } static void someFunction() { Printer::log(M_DEBUG, "ObjectTest::someFunction() called."); callCount++; } + static void someStatic() { Printer::log(M_DEBUG, "ObjectTest::someStatic() called."); callCount++; } }; enum ObjectTest_methods_t { @@ -23,8 +24,9 @@ enum ObjectTest_methods_t { }; enum ObjectTest_functions_t { - OBJECTTEST_CREATEOBJECTTEST, + OBJECTTEST_CONSTRUCTOR, OBJECTTEST_SOMEFUNCTION, + OBJECTTEST_SOMESTATIC, OBJECTTEST_YIELDTEST, }; @@ -35,8 +37,9 @@ struct lua_functypes_t ObjectTest_methods[] = { }; struct lua_functypes_t ObjectTest_functions[] = { - { OBJECTTEST_CREATEOBJECTTEST, "createObjectTest", 0, 0, { } }, + { OBJECTTEST_CONSTRUCTOR, NULL, 0, 0, { } }, { OBJECTTEST_SOMEFUNCTION, "ObjectTestFunction", 0, 0, { } }, + { OBJECTTEST_SOMESTATIC, "SomeStatic", 0, 0, { } }, { OBJECTTEST_YIELDTEST, "yieldTest", 1, 1, { BLUA_NUMBER } }, { -1, 0, 0, 0, 0 }, }; @@ -46,7 +49,8 @@ class sLua_ObjectTest { DECLARE_METHOD(ObjectTest, OBJECTTEST_SOMEMETHOD1); DECLARE_METHOD(ObjectTest, OBJECTTEST_SOMEMETHOD2); - DECLARE_FUNCTION(ObjectTest, OBJECTTEST_CREATEOBJECTTEST); + DECLARE_CONSTRUCTOR(ObjectTest, OBJECTTEST_CONSTRUCTOR); + DECLARE_STATIC(ObjectTest, OBJECTTEST_SOMESTATIC); DECLARE_FUNCTION(ObjectTest, OBJECTTEST_SOMEFUNCTION); DECLARE_FUNCTION(ObjectTest, OBJECTTEST_YIELDTEST); private: @@ -61,9 +65,11 @@ class LuaObjectTestFactory : public LuaObjectFactory { CHECK_METHODS(ObjectTest); CHECK_FUNCTIONS(ObjectTest); - PUSH_FUNCTION(ObjectTest, OBJECTTEST_CREATEOBJECTTEST); + PUSH_CONSTRUCTOR(ObjectTest, OBJECTTEST_CONSTRUCTOR); + PUSH_STATIC(ObjectTest, OBJECTTEST_SOMESTATIC); PUSH_FUNCTION(ObjectTest, OBJECTTEST_SOMEFUNCTION); PUSH_FUNCTION(ObjectTest, OBJECTTEST_YIELDTEST); + PUSH_CLASS_DONE(); } private: void pushObjectAndMembers(Lua & L) { @@ -96,7 +102,7 @@ int sLua_ObjectTest::ObjectTest_proceed_statics(Lua & L, int n, int caller) thro int y; switch (caller) { - case OBJECTTEST_CREATEOBJECTTEST: + case OBJECTTEST_CONSTRUCTOR: { ObjectTest * ot = new ObjectTest; LuaObjectTestFactory factory(ot); @@ -105,6 +111,10 @@ int sLua_ObjectTest::ObjectTest_proceed_statics(Lua & L, int n, int caller) thro return 1; break; + case OBJECTTEST_SOMESTATIC: + ObjectTest::someStatic(); + break; + case OBJECTTEST_SOMEFUNCTION: ObjectTest::someFunction(); break; @@ -187,6 +197,11 @@ void MainTask::Do() { TAssert(callCount == 3); + L.load("ObjectTest.SomeStatic()"); + TAssert(L.gettop() == 0); + + TAssert(callCount == 4); + L.load("yieldTest(0)"); while (L.yielded()) { waitFor(LuaHelpersBase::getEvent(L)); @@ -201,9 +216,9 @@ void MainTask::Do() { TAssert(L.gettop() == 0); TAssert(objGotDestroyed == 0); - L.load("obj2 = createObjectTest() obj2:destroy()"); + L.load("obj2 = ObjectTest.new() obj2:destroy()"); TAssert(objGotDestroyed == 1); - L.load("createObjectTest() collectgarbage('collect')"); + L.load("ObjectTest.new() collectgarbage('collect')"); TAssert(objGotDestroyed == 2); L.close(); TAssert(objGotDestroyed == 3); -- cgit v1.2.3