summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Noble <pixel@nobis-crew.org>2013-07-31 11:31:38 -0700
committerNicolas Noble <pixel@nobis-crew.org>2013-07-31 11:31:38 -0700
commit5ce610659adea3159549d4863c2479163fce89f4 (patch)
treee89d1084386d551bd42def29a5a3507c7e3f0c2c
parented4e627d314bff09013dbd5547b2dcb40eb43037 (diff)
Even further changes in the Lua class binding system. Simplifying the callback system by using the Lua's C closure mechanism.
-rw-r--r--includes/BLua.h164
-rw-r--r--src/BLua.cc26
-rw-r--r--tests/test-Lua.cc15
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<class T>
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<size_t S>
+ static void pushMethod(Lua & L, const char (&str)[S], lua_CFunction func, int upvalues = 0) {
+ pushMethod(L, str, S - 1, func, upvalues);
+ }
+ template<size_t S>
+ 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<size_t S>
+ 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<classname>::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<classname>::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<classname>::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<classname>::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<classname>::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<classname>::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<classname>::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<classname>::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<classname>::method_multiplex_closure, 5); \
+ L.settable(LUA_GLOBALSINDEX); \
+}
#define PUSH_CLASS_DONE() L.pop()
@@ -347,14 +353,28 @@ class LuaHelpersBase {
template <class T>
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) {