From df0444f85f9bf623cc886e1632e624ef20cb0f1b Mon Sep 17 00:00:00 2001 From: chai Date: Sat, 23 Oct 2021 00:31:25 +0800 Subject: -member table --- Runtime/Lua/LuaBind/LuaBindClass.hpp | 348 ++++++----------------------------- 1 file changed, 58 insertions(+), 290 deletions(-) (limited to 'Runtime/Lua/LuaBind/LuaBindClass.hpp') diff --git a/Runtime/Lua/LuaBind/LuaBindClass.hpp b/Runtime/Lua/LuaBind/LuaBindClass.hpp index f0fdf43..c112c03 100644 --- a/Runtime/Lua/LuaBind/LuaBindClass.hpp +++ b/Runtime/Lua/LuaBind/LuaBindClass.hpp @@ -36,7 +36,6 @@ namespace LuaBind // 成员引用管理,在实例的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资源。 @@ -56,7 +55,7 @@ namespace LuaBind class NativeClass : public BASE { public: - enum NativeClassTableIndex { kRefTable = 1, kMemberTable = 2, kClassTable = 3 }; + enum NativeClassTableIndex { kRefTable = 1, kClassTable = 2 }; // 将userdata作为key,在ref table里对userdata添加一个引用,以维持userdata的生命周期。 // 相比较member ref,这个用在实体会被多次被不同其他实体引用的情况,并频繁销毁这些实体, @@ -70,7 +69,6 @@ namespace LuaBind // userdata留在栈顶。并添加一个引用。这是一个将native对象所有权移交给lua控制的方法。 bool PushUserdata(State& state) override; bool PushMemberRef(State& state, int refID) override; - bool PushMemberTable(State& state) override; bool PushRefTable(State& state) override; // WatchDog添加一个native引用。luaVM引用不会提供外部接口。继承此类的派生类不能直接使用 @@ -102,7 +100,7 @@ namespace LuaBind friend class State; static void RegisterClassShared(State& state); - static void RegisterFactoryClass(State& state); + static void RegisterNativeClass(State& state); static void SetClassTableRef(State& state, int idx); static void PushClassTable(State& state); @@ -121,13 +119,6 @@ namespace LuaBind static int __gc (lua_State*); static int _GetRefTable (lua_State*); -#if LUA_BIND_ENABLE_NATIVE_EXTEND - static int _New(lua_State*); - - static int _ExtendFactory (lua_State*); - static int _ExtendSingleton (lua_State*); -#endif - //--------------------------------------------------------------------------------// // 类型的全局UID,在不同的虚拟机中相同 @@ -138,8 +129,7 @@ namespace LuaBind // 通过userdata可以拿到: // 1: ref table - // 2: member table - // 3: class table + // 2: class table WeakRef mUserdata; // 通过后才能删除 @@ -154,27 +144,6 @@ namespace LuaBind }; -#if LUA_BIND_ENABLE_PLAIN_CLASS - // - // 纯lua类 - // - class PlainClass - { - public: - - // - // 用来注册类的入口函数。可以通过registry(类名)注册类。 - // - static int registry(lua_State* L); - - LUA_BIND_DECL_METHOD(__tostring); - LUA_BIND_DECL_METHOD(_Extend); - LUA_BIND_DECL_METHOD(_New); - LUA_BIND_DECL_METHOD(_TypeOf); - - }; -#endif - //--------------------------------------------------------------------------------// template int NativeClass::sClassID = CLASS_NONE_ID; @@ -207,7 +176,7 @@ namespace LuaBind // 工厂类的成员,注册在class table template - void NativeClass::RegisterFactoryClass(State& state) + void NativeClass::RegisterNativeClass(State& state) { luaL_Reg regTable[] = { { "GetRefTable", _GetRefTable }, @@ -347,27 +316,6 @@ namespace LuaBind return mUserdata.PushRef(state); } - template - bool NativeClass::PushMemberTable(State& state) - { - int top = state.GetTop(); - if (this->PushUserdata(state)) - { - if (lua_getmetatable(state, -1)) // ref table - { - lua_replace(state, -2); - if (lua_getmetatable(state, -1)) // member table - { - lua_replace(state, -2); - return true; - } - } - } - lua_settop(state, top); - lua_pushnil(state); - return false; - } - template bool NativeClass::PushRefTable(State& state) { @@ -383,8 +331,7 @@ namespace LuaBind } // 创建userdata,并以此添加ref table,member table和class table。 - // ref table 是kv强引用table,保存对其他userdata的引用计数(通过userdata作为key, - // 计数为value),以及成员引用 + // ref table 是kv强引用table,保存对其他GCObject的引用 // member table 保存lua创建的实例的成员 // class table 所有本类型的实例共有的函数表 // @@ -392,70 +339,67 @@ namespace LuaBind template void NativeClass::BindToLua(State& state) { - assert(!mUserdata); - - // 创建userdata并留在栈顶,注意地址要转换为TYPE*,直接用this可能会导致多重继承的类丧失多态。 - // 如果直接传this进去,在多重继承情况下,是拿不到另一头的虚函数表的。所以这里需要将this - // 转换为整个对象的低地址,这样可以拿到另一个基类的虚函数表,通过另一个基类实现多态。 - TYPE* p = static_cast(this); - state.PushPtrUserdata(p); - - lua_newtable(state); // ref table,无法在lua处访问,用来管理C对象的生命周期 - lua_newtable(state); // member table,lua中创建的对象成员都保存在这里 - PushClassTable(state); // class table - - // stack: - // -1 class table - // -2 member table - // -3 ref table - // -4 userdata - - int top = state.GetTop(); - int memberTable = top - 1; - int refTable = top - 2; - - // ref table 注册 __tostring 和 __gc - lua_pushcfunction(state, __tostring); - lua_setfield(state, refTable, "__tostring"); - - lua_pushcfunction(state, __gc); - lua_setfield(state, refTable, "__gc"); - - // ref table 的 __index 和 __newindex 设为 member table - lua_pushvalue(state, memberTable); - lua_setfield(state, refTable, "__index"); - - lua_pushvalue(state, memberTable); - lua_setfield(state, refTable, "__newindex"); - - // 设置元表 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); - assert(mUserdata); - - // 增加一个虚拟机引用,在GC时-1 - ++mWatchDog.mVMRef; -#if LUA_BIND_PROFILER - mRefVMs.insert(state.GetVM()); + assert(!mUserdata); + + // 创建userdata并留在栈顶,注意地址要转换为TYPE*,直接用this可能会导致多重继承的类丧失多态。 + // 如果直接传this进去,在多重继承情况下,是拿不到另一头的虚函数表的。所以这里需要将this + // 转换为整个对象的低地址,这样可以拿到另一个基类的虚函数表,通过另一个基类实现多态。 + TYPE* p = static_cast(this); + state.PushPtrUserdata(p); + + lua_newtable(state); // ref table,无法在lua处访问,用来管理C对象的生命周期 + //lua_newtable(state); // member table,lua中创建的对象成员都保存在这里 + PushClassTable(state); // class table + + // stack: + // -1 class table + // -2 ref table + // -3 userdata + + int clsTable = state.GetTop(); + int refTable = clsTable - 1; + + // ref table 注册 __tostring 和 __gc + lua_pushcfunction(state, __tostring); + lua_setfield(state, refTable, "__tostring"); + + lua_pushcfunction(state, __gc); + lua_setfield(state, refTable, "__gc"); + + // ref table 的 __index 和 __newindex 设为 member table + lua_pushvalue(state, clsTable); + lua_setfield(state, refTable, "__index"); + + lua_pushvalue(state, clsTable); + lua_setfield(state, refTable, "__newindex"); + + // 设置元表 userdata -> refTable -> classTable + lua_setmetatable(state, -2); // class is metatable of ref + lua_setmetatable(state, -2); // ref is metatable of userdata + + // 设置一个userdata的弱引用,方便通过PushLuaUserdata方法返回lua对象 + mUserdata.SetRef(state, -1); + assert(mUserdata); + + // 增加一个虚拟机引用,在GC时-1 + ++mWatchDog.mVMRef; +#if LUA_BIND_PROFILER + mRefVMs.insert(state.GetVM()); #endif } // 成员引用管理 template - void NativeClass::SetMemberRef(State& state, MemberRef& memRef, int idx) + void NativeClass::SetMemberRef(State& state, MemberRef& outRef, int idx) { - ClearMemberRef(state, memRef); + ClearMemberRef(state, outRef); if (!lua_isnil(state, idx)) { idx = state.AbsIndex(idx); - if (PushRefTable(state)) + if (PushRefTable(state)) // RefTable { lua_pushvalue(state, idx); - memRef.refID = luaL_ref(state, -2); + outRef.refID = luaL_ref(state, -2); state.Pop(); // ref table } } @@ -466,7 +410,7 @@ namespace LuaBind { if (memRef) { - if (PushRefTable(state)) + if (PushRefTable(state)) // RefTable { lua_rawgeti(state, -1, memRef.refID); lua_replace(state, -2); // ref table @@ -484,7 +428,7 @@ namespace LuaBind template bool NativeClass::PushMemberRef(State& state, int refID) { - if (PushRefTable(state)) + if (PushRefTable(state)) // RefTable { lua_rawgeti(state, -1, refID); lua_replace(state, -2); // ref table @@ -502,7 +446,7 @@ namespace LuaBind { if (memRef) { - if (PushRefTable(state)) + if (PushRefTable(state)) // RefTable { luaL_unref(state, -1, memRef.refID); state.Pop(); // ref table @@ -568,182 +512,6 @@ namespace LuaBind return 0; } -#if LUA_BIND_ENABLE_NATIVE_EXTEND - // 派生出子类,在lua里对派生类的成员和行为进行重新设计,但是保证了userdata的统一。Native class的派生提供__init支持,在 - // native实体创建后可以使用__init进行初始化,派生类拥有和基类一样的New参数列表,且native对象是一样的类型。 - template - int NativeClass::_ExtendFactory(lua_State* L) - { - // upvalues: - // 1: base class - - // params: - // 1: class name - - int baseClass = lua_upvalueindex(1); - - lua_newtable(L); // class table - - int inheritClass = lua_gettop(L); - - // .GetClassName() - cc8* type = lua_tostring(L, 1); - lua_pushstring(L, type); - lua_pushcclosure(L, luax_c_getupvalue, 1); - lua_setfield(L, -2, "GetClassName"); - - // .GetClass() - lua_pushvalue(L, inheritClass); - lua_pushcclosure(L, luax_c_getupvalue, 1); - lua_setfield(L, -2, "GetClass"); - - // .Extend() - lua_pushvalue(L, inheritClass); - lua_pushcclosure(L, _ExtendFactory, 1); - lua_setfield(L, -2, "Extend"); - - // .New() - lua_pushvalue(L, inheritClass); - lua_getfield(L, baseClass, "New"); - lua_pushcclosure(L, _New, 2); - lua_setfield(L, -2, "New"); - - // __base = baseClass - lua_pushvalue(L, baseClass); - lua_setfield(L, -2, "__base"); - - // __index = inheritClass - lua_pushvalue(L, inheritClass); - lua_setfield(L, -2, "__index"); - - // metatable is baseClass - lua_pushvalue(L, baseClass); - lua_setmetatable(L, inheritClass); - - return 1; - } - - template - int NativeClass::_ExtendSingleton(lua_State* L) - { - // upvalues: - // 1: base class - - // params: - // 1: class name - - int baseClass = lua_upvalueindex(1); - - lua_newtable(L); // class name - - int inheritClass = lua_gettop(L); - - // .GetClassName() - cc8* type = lua_tostring(L, 1); - lua_pushstring(L, type); - lua_pushcclosure(L, luax_c_getupvalue, 1); - lua_setfield(L, -2, "GetClassName"); - - // .GetClass() - lua_pushvalue(L, inheritClass); - lua_pushcclosure(L, luax_c_getupvalue, 1); - lua_setfield(L, -2, "GetClass"); - - // .Extend() - lua_pushvalue(L, inheritClass); - lua_pushcclosure(L, _ExtendFactory, 1); - lua_setfield(L, -2, "Extend"); - - // __base = baseClass - lua_pushvalue(L, baseClass); - lua_setfield(L, -2, "__base"); - - // __index = inheritClass - lua_pushvalue(L, inheritClass); - lua_setfield(L, -2, "__index"); - - // metatable is baseClass - lua_pushvalue(L, baseClass); - lua_setmetatable(L, inheritClass); - - return 1; - } - - template - int NativeClass::_New(lua_State* L) - { - LUA_BIND_STATE(L); - - // upvalues: - // 1: class table - // 2: original New() - - // stack: - // -1~-n: args - - int n = lua_gettop(L); // n args - - lua_pushvalue(L, lua_upvalueindex(2)); - if (state.IsType(-1, LUA_TFUNCTION)) - { - // stack: - // -1: New - // -2~-1-n: args - - state.PushValues(-1 - n, n); - - // stack: - // -1~-n: args - // -n-1: New - // -n-2~-1-2n: args - - state.Call(n, 1); - - // stack: - // -1: userdata - // -2~-1-n: args - - // reset member table's metatable to class table - if (state.IsType(-1, LUA_TUSERDATA)) - { - if (lua_getmetatable(L, -1)) // ref table - { - if (lua_getmetatable(L, -1)) // member table - { - lua_pushvalue(L, lua_upvalueindex(1)); // class table - lua_setmetatable(L, -2); - state.Pop(); // member table - } - state.Pop(); // ref table - } - - // stack: - // -1: userdata - // -2~-1-n: args - - int args = state.AbsIndex(-1 - n); - - // 尝试调用__init函数 - lua_getfield(L, lua_upvalueindex(1), "__init"); - - if (state.IsType(-1, LUA_TFUNCTION)) - { - lua_pushvalue(L, -2); // userdata - state.PushValues(args, n); - state.Call(n + 1, 0); - } - else - state.Pop(); - - } - - return 1; - } - return 0; - } - -#endif /*LUA_BIND_ENABLE_NATIVE_EXTEND*/ - template int NativeClass::_GetClass(lua_State* L) { -- cgit v1.1-26-g67d0