summaryrefslogtreecommitdiff
path: root/Runtime/Lua/LuaBind/LuaBindState.h
diff options
context:
space:
mode:
Diffstat (limited to 'Runtime/Lua/LuaBind/LuaBindState.h')
-rw-r--r--Runtime/Lua/LuaBind/LuaBindState.h181
1 files changed, 180 insertions, 1 deletions
diff --git a/Runtime/Lua/LuaBind/LuaBindState.h b/Runtime/Lua/LuaBind/LuaBindState.h
index 1f236df..ec2a350 100644
--- a/Runtime/Lua/LuaBind/LuaBindState.h
+++ b/Runtime/Lua/LuaBind/LuaBindState.h
@@ -9,13 +9,16 @@
namespace LuaBind
{
-
class VM;
class Enum;
class StrongRef;
class WeakRef;
typedef void (*ErrorHandler) (cc8 * msg);
+ typedef void(*OnRegisterClassHandler)(State&, int clsIdx, std::string clsName, std::string pkgName);
+
+ extern OnRegisterClassHandler onRegisterFactoryClass;
+ extern std::string g_NameSpace;
// 对lua_State的代理,除了保存一个lua_State的引用不保存其他内容。一个实例的metatable如下:
// class table
@@ -264,6 +267,182 @@ namespace LuaBind
};
+ // 注册工厂,注册class table,以type name为键设置在名称空间上。在注册阶段不会设置元表,等到New方法调用的时候才会。
+ template<class TYPE>
+ void State::RegisterFactory()
+ {
+ cc8* type = TYPE::GetFactoryName();
+
+ lua_State* L = mState;
+ State& state = *this;
+
+ int top = lua_gettop(L); // namespace table
+ assert(lua_istable(L, top));
+
+ // class table
+ lua_newtable(L);
+ int clsIdx = lua_gettop(L);
+ TYPE::RegisterClassShared(state);
+ TYPE::RegisterFactoryClass(state);
+ TYPE::RegisterClass(state);
+
+ // 自定义流程
+ if (onRegisterFactoryClass)
+ onRegisterFactoryClass(state, clsIdx, type, g_NameSpace);
+
+ // 检测TYPE里面是否没有注册必须的方法
+#define _assertmethod(I, NAME) \
+ GetField(I, NAME); \
+ assert(IsType(-1, LUA_TFUNCTION)); \
+ Pop();
+
+ //_assertmethod(-1, "New");
+#undef _assertmethod
+
+#if LUA_BIND_ENABLE_NATIVE_EXTEND
+ // .Extend()
+ lua_pushvalue(state, -1); // class table
+ lua_pushcclosure(state, TYPE::_ExtendFactory, 1);
+ lua_setfield(state, -2, "Extend");
+#endif
+
+ // class["__index"] = class
+ lua_pushvalue(state, -1); // class table
+ lua_setfield(state, -2, "__index");
+
+ TYPE::SetClassTableRef(state, -1);
+
+ SetField(top, type);
+
+ // reset top
+ lua_settop(L, top);
+
+ // 后处理
+ TYPE::RegisterPostprocess(state);
+ }
+
+ // 注册单例
+ template<typename TYPE>
+ void State::RegisterSingleton()
+ {
+ lua_State* L = mState;
+ State& state = *this;
+
+ int top = lua_gettop(L); // namespace table
+ assert(lua_istable(L, top));
+
+ // class table.
+ lua_newtable(L);
+ TYPE::RegisterClassShared(state);
+ TYPE::RegisterSingletonClass(state);
+ TYPE::RegisterClass(state);
+
+ TYPE::SetClassTableRef(state, -1);
+
+ lua_pushvalue(state, -1);
+ lua_setfield(state, -2, "__index");
+
+#if LUA_BIND_ENABLE_NATIVE_EXTEND
+ // .Extend()
+ lua_pushvalue(state, -1); // class table
+ lua_pushcclosure(state, TYPE::_ExtendSingleton, 1);
+ lua_setfield(state, -2, "Extend");
+#endif
+
+ cc8* type = TYPE::GetSingletonName();
+ SetField(top, type);
+
+ // reset top
+ lua_settop(L, top);
+
+ // 后处理
+ TYPE::RegisterPostprocess(state);
+ }
+
+ template<typename TYPE>
+ void State::SetField(int idx, cc8* key, TYPE value)
+ {
+ if (IsTableOrUserdata(idx))
+ {
+ idx = AbsIndex(idx);
+ this->Push(value);
+ lua_setfield(mState, idx, key);
+ }
+ }
+
+ template<typename TYPE>
+ void State::SetFieldByIndex(int idx, int key, TYPE value)
+ {
+ if (IsTableOrUserdata(idx))
+ {
+ idx = AbsIndex(idx);
+ this->Push(value);
+ lua_rawseti(mState, idx, key);
+ }
+ }
+
+ template<typename TYPE>
+ TYPE State::GetField(int idx, cc8* key, TYPE value)
+ {
+ GetField(idx, key);
+ TYPE result = GetValue < TYPE >(-1, value);
+ this->Pop();
+
+ return result;
+ }
+
+ template<typename TYPE>
+ TYPE State::GetField(int idx, int key, TYPE value)
+ {
+ GetField(idx, key);
+ TYPE result = GetValue < TYPE >(-1, value);
+ Pop();
+
+ return result;
+ }
+
+ template<typename TYPE>
+ TYPE* State::GetUserdata(int idx)
+ {
+ void* p = nullptr;
+
+ if (IsType(idx, LUA_TUSERDATA))
+ {
+ p = *(void**)lua_touserdata(mState, idx);
+ }
+
+ return static_cast<TYPE*>(p);
+ }
+
+ template<typename TYPE>
+ TYPE* State::CheckUserdata(int idx)
+ {
+ if (IsType(idx, LUA_TUSERDATA))
+ {
+ if (lua_getmetatable(mState, idx)) // ref table
+ {
+ if (lua_getmetatable(mState, -1)) // member table
+ {
+ if (lua_getmetatable(mState, -1)) // class table
+ {
+ TYPE::PushClassTable(*this); // target class table
+ if (lua_rawequal(mState, -1, -2))
+ {
+ Pop(4); // ref\member\class\target class
+ TYPE* udata = GetUserdata<TYPE>(idx);
+ return udata; // userdata
+ }
+ Pop(2); // target class table\class table
+ }
+ Pop(1); // member table
+ }
+ Pop(1); // ref table
+ }
+ }
+ luaL_typerror(mState, idx, TYPE::GetClassName());
+ return nullptr;
+ }
+
}
#endif \ No newline at end of file