diff options
author | chai <chaifix@163.com> | 2021-10-22 23:59:54 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2021-10-22 23:59:54 +0800 |
commit | 4dafefe46a72ba47468b13d011f8299055081b0f (patch) | |
tree | 2a85835ec4d74fecf3815397b384cefe39d31f56 /Runtime/Lua/LuaBind/LuaBindClass.hpp | |
parent | 1f18d2afec632aa9361079ca3bcb5a7f2d73db3a (diff) |
*LuaBind
Diffstat (limited to 'Runtime/Lua/LuaBind/LuaBindClass.hpp')
-rw-r--r-- | Runtime/Lua/LuaBind/LuaBindClass.hpp | 150 |
1 files changed, 40 insertions, 110 deletions
diff --git a/Runtime/Lua/LuaBind/LuaBindClass.hpp b/Runtime/Lua/LuaBind/LuaBindClass.hpp index 154a4ce..f0fdf43 100644 --- a/Runtime/Lua/LuaBind/LuaBindClass.hpp +++ b/Runtime/Lua/LuaBind/LuaBindClass.hpp @@ -2,25 +2,24 @@ #define __LUA_BIND_CLASS_H__ #include "LuaBindConfig.h" - -#if LUA_BIND_PROFILER #include <unordered_set> -#endif - +#include <unordered_map> #include <vector> - #include "LuaBindRef.h" #include "LuaBindMemberRef.h" #include "LuaBindCFunctions.h" #include "LuaBindWatchDog.h" #include "LuaBindUtility.h" +#include "LuaBindHelper.h" namespace LuaBind { - class VM; - // +#define CLASS_NONE_ID (-1) + + extern UIDGenerator gClassIDGenerator; + // 虚基类,为了实现多态。需要访问下面这些接口的外部基类需要虚继承此类,之后再派生链中就会 // 调用对应实体的方法。注意继承此类时不能实现下面的方法,实现在NativeClass中,实现会 // 导致二义性。 @@ -28,24 +27,19 @@ namespace LuaBind // 依据Effective C++条款40,如果在必须使用virtual base基类情况下,应该尽可能避免向其中放 // 置数据成员,规避数据成员初始化造成的一些隐性问题。依据这一点,vpb基类更加接近C#和Java中 // 的Interface。所以,在这里把类用I开头标识这是一个接口。 - // class Object { public: Object() {}; virtual ~Object() {}; - // // 成员引用管理,在实例的ref table里。设置、取、清除。 - // virtual bool PushMemberRef(State& state, int refID) = 0; virtual bool PushUserdata(State& state) = 0; virtual bool PushMemberTable(State& state) = 0; virtual bool PushRefTable(State& state) = 0; - // // 被NativeClass实现。保持和释放native资源。 - // virtual void Retain() = 0; virtual void Release() = 0; @@ -56,43 +50,34 @@ namespace LuaBind //{ //} - // // 需要暴露给lua的native class需要继承此类。通过lua管理的实例要确保引用计数的正确性,在多个线程中需要确 // 定不会误释放。 - // template<class TYPE, class BASE = Object> class NativeClass : public BASE { public: + enum NativeClassTableIndex { kRefTable = 1, kMemberTable = 2, kClassTable = 3 }; - // // 将userdata作为key,在ref table里对userdata添加一个引用,以维持userdata的生命周期。 // 相比较member ref,这个用在实体会被多次被不同其他实体引用的情况,并频繁销毁这些实体, // 避免lua频繁的调用gc检测。 - // template<class DATATYPE> void Retain(State& state, DATATYPE* userdata); - // // 对userdata减少一个引用在ref table里,以尝试回收userdata。 - // template<class DATATYPE> void Release(State& state, DATATYPE* userdata); - // // 将userdata push到栈顶,如果没有初始化mUserdata,初始化设置好元表并把初始化好的 // userdata留在栈顶。并添加一个引用。这是一个将native对象所有权移交给lua控制的方法。 - // + bool PushUserdata(State& state) override; bool PushMemberRef(State& state, int refID) override; - bool PushUserdata(State& state) override; bool PushMemberTable(State& state) override; bool PushRefTable(State& state) override; - // // WatchDog添加一个native引用。luaVM引用不会提供外部接口。继承此类的派生类不能直接使用 // delete方法,应该使用Release释放。一般情况下这个操作由虚拟机__gc进行,但是允许用户 // 程序在native中隔绝虚拟机情况下释放,这种情况下要使用Release。 // // 这两个函数是native接口。 - // void Retain() override final; void Release() override final; @@ -103,12 +88,11 @@ namespace LuaBind protected: - NativeClass(); + // 需要指明对象所属的虚拟机 + NativeClass(LuaBind::VM* vm); virtual ~NativeClass(); - // // 成员引用管理,在实例的ref table里。设置、取、清除 - // void SetMemberRef(State& state, MemberRef& memRef, int idx); bool PushMemberRef(State& state, MemberRef& memRef); void ClearMemberRef(State& state, MemberRef& memRef); @@ -119,14 +103,11 @@ namespace LuaBind static void RegisterClassShared(State& state); static void RegisterFactoryClass(State& state); - static void RegisterSingletonClass(State& state); static void SetClassTableRef(State& state, int idx); static void PushClassTable(State& state); - // // 创建userdata,绑定实例到state。 - // void BindToLua(State& state); //------------------------------------------------------------------------------// @@ -149,25 +130,16 @@ namespace LuaBind //--------------------------------------------------------------------------------// - // - // class table,工厂和单例都有。 - // - static StrongRef mClassTable; + // 类型的全局UID,在不同的虚拟机中相同 + static int sClassID; - // - // 如果类是单例,这个用来保存singleton的引用关系,以保证不会被回收类似普通类的ref table。 - // 单例的成员是全生命周期的,所以直接在_LUA_BIND_STRONGREF_TABLE。单例对userdata进行 - // Retain\Release和member ref操作时和工厂实例不同,是存在下面这个ref table里 - // 的,这个table在_LUA_BIND_STRONGREF_TABLE里。 - // - static StrongRef mSingletonRefTable; + // 所属的虚拟机 + LuaBind::VM* mOwner; - // // 通过userdata可以拿到: // 1: ref table // 2: member table // 3: class table - // WeakRef mUserdata; // 通过后才能删除 @@ -204,10 +176,10 @@ namespace LuaBind #endif //--------------------------------------------------------------------------------// + template<class TYPE, class BASE> + int NativeClass<TYPE, BASE>::sClassID = CLASS_NONE_ID; - // // 对不同类型,通过调用GetLuaClassName获得类型名,如果是派生类,GetClassName会被覆盖,指向luax_c_getupvalue。 - // template<class TYPE, class BASE> int NativeClass<TYPE, BASE>::_GetClassName(lua_State* L) { @@ -220,9 +192,7 @@ namespace LuaBind //--------------------------------------------------------------------------------// - // // 注册工厂和单例共有的类成员 - // template<class TYPE, class BASE> void NativeClass<TYPE, BASE>::RegisterClassShared(State& state) { @@ -235,9 +205,7 @@ namespace LuaBind state.RegisterMethods(regTable); } - // // 工厂类的成员,注册在class table - // template<class TYPE, class BASE> void NativeClass<TYPE, BASE>::RegisterFactoryClass(State& state) { @@ -249,36 +217,27 @@ namespace LuaBind state.RegisterMethods(regTable); } - // - // 单例类的成员,注册在class table - // template<class TYPE, class BASE> - void NativeClass<TYPE, BASE>::RegisterSingletonClass(State& state) + void NativeClass<TYPE, BASE>::SetClassTableRef(State& state, int idx) { - luaL_Reg regTable[] = { - { NULL, NULL } - }; - - state.RegisterMethods(regTable); + if (sClassID == CLASS_NONE_ID) + sClassID = gClassIDGenerator.GetID(); + LuaBind::VM* vm = state.GetVM(); + vm->RegisterClassI(state, sClassID, idx); } template<class TYPE, class BASE> void NativeClass<TYPE, BASE>::PushClassTable(State& state) { - assert(mClassTable); - - mClassTable.PushRef(state); + LuaBind::VM* vm = state.GetVM(); + vm->PushClassTable(state, sClassID); } template<class TYPE, class BASE> - void NativeClass<TYPE, BASE>::SetClassTableRef(State& state, int idx) - { - mClassTable.SetRef(state, idx); - } - - template<class TYPE, class BASE> - NativeClass<TYPE, BASE>::NativeClass() + NativeClass<TYPE, BASE>::NativeClass(LuaBind::VM* vm) : mWatchDog() + , mUserdata(vm) + , mOwner(vm) #if LUA_BIND_PROFILER , mSafer(false) #endif @@ -380,8 +339,7 @@ namespace LuaBind template<class TYPE, class BASE> bool NativeClass<TYPE, BASE>::PushUserdata(State& state) { - assert(!TYPE::IsClassSingleton()); - if (!mUserdata) + if (!mUserdata) // 第一次创建 { BindToLua(state); return true; @@ -413,28 +371,12 @@ namespace LuaBind template<class TYPE, class BASE> bool NativeClass<TYPE, BASE>::PushRefTable(State& state) { - // Singleton - if (TYPE::IsClassSingleton()) - { - if (!this->mSingletonRefTable) { - lua_newtable(state); - this->mSingletonRefTable.SetRef(state, -1); // strong ref to member table won't be garbage collected - } - else { - this->mSingletonRefTable.PushRef(state); - } - return true; - } - // Factory - else + if (this->PushUserdata(state)) { - if (this->PushUserdata(state)) + if (lua_getmetatable(state, -1)) // RefTable { - if (lua_getmetatable(state, -1)) - { - lua_replace(state, -2); - return true; - } + lua_replace(state, -2); + return true; } } return false; @@ -450,8 +392,6 @@ namespace LuaBind template<class TYPE, class BASE> void NativeClass<TYPE, BASE>::BindToLua(State& state) { - // 单例不能绑定userdata - assert(!TYPE::IsClassSingleton()); assert(!mUserdata); // 创建userdata并留在栈顶,注意地址要转换为TYPE*,直接用this可能会导致多重继承的类丧失多态。 @@ -465,10 +405,10 @@ namespace LuaBind PushClassTable(state); // class table // stack: - // -1: class table - // -2: member table - // -3: ref table - // -4: userdata + // -1 class table + // -2 member table + // -3 ref table + // -4 userdata int top = state.GetTop(); int memberTable = top - 1; @@ -488,10 +428,10 @@ namespace LuaBind lua_pushvalue(state, memberTable); lua_setfield(state, refTable, "__newindex"); - // 设置元表 - lua_setmetatable(state, -2); // class is meta of member - lua_setmetatable(state, -2); // member is meta of ref - lua_setmetatable(state, -2); // ref is meta of userdata + // 设置元表 userdata -> refTable -> memberTable -> classTable + lua_setmetatable(state, -2); // class is metatable of member + lua_setmetatable(state, -2); // member is metatable of ref + lua_setmetatable(state, -2); // ref is metatable of userdata // 设置一个userdata的弱引用,方便通过PushLuaUserdata方法返回lua对象 mUserdata.SetRef(state, -1); @@ -504,9 +444,7 @@ namespace LuaBind #endif } - // // 成员引用管理 - // template<class TYPE, class BASE> void NativeClass<TYPE, BASE>::SetMemberRef(State& state, MemberRef& memRef, int idx) { @@ -810,10 +748,7 @@ namespace LuaBind int NativeClass<TYPE, BASE>::_GetClass(lua_State* L) { LUA_BIND_STATE(L); - if (!mClassTable) - lua_pushnil(L); - else - mClassTable.PushRef(state); + state.GetVM()->PushClassTable(state, sClassID); return 1; } @@ -828,11 +763,6 @@ namespace LuaBind return 1; } - template<class TYPE, class BASE> StrongRef NativeClass<TYPE, BASE>::mClassTable; // class table - template<class TYPE, class BASE> StrongRef NativeClass<TYPE, BASE>::mSingletonRefTable; // 单例 - - - } #endif
\ No newline at end of file |