From d29f5f4aebd90b1e256967801b28a5990249b2e7 Mon Sep 17 00:00:00 2001 From: chai Date: Sat, 16 Mar 2019 19:29:23 +0800 Subject: *luax --- Source/3rdParty/Luax/luax_class.inl | 182 ++++++++++++++++++++++++++++++++---- 1 file changed, 162 insertions(+), 20 deletions(-) (limited to 'Source/3rdParty/Luax/luax_class.inl') diff --git a/Source/3rdParty/Luax/luax_class.inl b/Source/3rdParty/Luax/luax_class.inl index 8cf0f55..bbda6de 100644 --- a/Source/3rdParty/Luax/luax_class.inl +++ b/Source/3rdParty/Luax/luax_class.inl @@ -5,7 +5,7 @@ namespace Luax // 接口 /// - /// 对不同类型,通过调用GetLuaClassName获得类型名 + /// 对不同类型,通过调用GetLuaClassName获得类型名,如果是派生类,GetClassName会被覆盖,指向luax_c_getupvalue。 /// template int LuaxClass::l_GetClassName(lua_State* L) @@ -33,7 +33,6 @@ namespace Luax state.RegisterMethods(regTable); } - /// /// 工厂类的成员,注册在class table /// @@ -48,7 +47,6 @@ namespace Luax state.RegisterMethods(regTable); } - /// /// 工厂实例的成员,注册在interface table /// @@ -56,14 +54,14 @@ namespace Luax void LuaxClass::RegisterLuaxInterface(LuaxState& state) { luaL_Reg regTable[] = { - { "__gc", l___gc }, - { NULL, NULL } + { "GetClass", l_GetClass }, + { "GetRefTable", l_GetRefTable }, + { NULL, NULL } }; state.RegisterMethods(regTable); } - /// /// 单例类的成员,注册在class table /// @@ -107,30 +105,55 @@ namespace Luax template LuaxClass::LuaxClass() - : mRC(1) // 构造时默认有一个引用 - , mSafer(false) { } template LuaxClass::~LuaxClass() { - assert(mSafer); } template - void LuaxClass::Retain() + template + void LuaxClass::LuaRetain(LuaxState& state, U* userdata) { - ++mRC; + if (PushLuaxRefTable(state)) + { + if (userdata->PushLuaxUserdata(state)) + { + lua_pushvalue(state, -1); // copy the userdata + lua_gettable(state, -3); // get the count (or nil) + u32 count = state.GetValue(-1, 0); // get the count (or 0) + lua_pop(state, 1); // pop the old count + lua_pushnumber(state, count + 1); // push the new count + lua_settable(state, -3); // save it in the table: reftable[userdata] = count + } + } } template - void LuaxClass::Release() + template + void LuaxClass::LuaRelease(LuaxState& state, U* userdata) { - if (--mRC <= 0) + if (PushLuaxRefTable(state)) { - mSafer = true; // 打开析构safer - delete this; + if (userdata->PushLuaxUserdata(state)) + { + lua_pushvalue(state, -1); // copy the userdata + lua_gettable(state, -3); // get the count (or nil) + u32 count = state.GetValue(-1, 0); // get the count (or 0) + lua_pop(state, 1); // pop the old count + + if (count == 0) return; // nothing to do + + if (count > 1) { + lua_pushnumber(state, count - 1); // push the new count + } + else { + lua_pushnil(state); // maybe cause gc + } + lua_settable(state, -3); // save it in the table + } } } @@ -197,6 +220,12 @@ namespace Luax return false; } + /// + /// 创建userdata,并以此添加ref table,member table和interface table。 + /// ref table 是kv强引用table,保存对其他userdata的引用计数(通过userdata作为key,计数为value),以及成员引用 + /// member table 保存lua创建的实例的成员 + /// interface table 所有本类型的实例共有的成员函数表 + /// template void LuaxClass::BindToLua(LuaxState& state) { @@ -221,14 +250,14 @@ namespace Luax int memberTable = top - 1; int refTable = top - 2; - // ref table 注册 __gc和__tostring + // ref table 注册 __gc 和 __tostring lua_pushcfunction(state, l___gc); lua_setfield(state, refTable, "__gc"); lua_pushcfunction(state, l___tostring); lua_setfield(state, refTable, "__tostring"); - // member table 设为 ref table 的 __index 和 __newindex + // ref table 的 __index 和 __newindex 设为 member table lua_pushvalue(state, memberTable); lua_setfield(state, refTable, "__index"); @@ -245,6 +274,59 @@ namespace Luax assert(mUserdata); } + /// + /// 成员引用管理 + /// + template + void LuaxClass::SetMemberRef(LuaxState& state, LuaxMemberRef& memRef, int idx) + { + ClearMemberRef(state, memRef); + if (!lua_isnil(state, idx)) + { + idx = state.AbsIndex(idx); + if (PushLuaxRefTable(state)) + { + lua_pushvalue(state, idx); + memRef.refID = luaL_ref(state, -2); + state.Pop(); // ref table + } + } + } + + template + bool LuaxClass::PushMemberRef(LuaxState& state, LuaxMemberRef& memRef) + { + if (memRef) + { + if (PushLuaxRefTable(state)) + { + lua_rawgeti(state, -1, memRef.refID); + lua_replace(state, -2); // ref table + if (lua_isnil(state, -1)) + goto failed; + return true; + } + } + lua_pushnil(state); + failed: + memRef.refID = LUA_NOREF; + return false; + } + + template + void LuaxClass::ClearMemberRef(LuaxState& state, LuaxMemberRef& memRef) + { + if (memRef) + { + if (PushLuaxRefTable(state)) + { + luaL_unref(state, -1, memRef.refID); + state.Pop(); // ref table + } + memRef.refID = LUA_NOREF; + } + } + //-------------------------------------------------------------------------------------------------------------- /// @@ -258,15 +340,51 @@ namespace Luax return 0; } + /// + /// 输出格式如下: + /// 地址 类名 + /// template int LuaxClass::l___tostring(lua_State* L) { + LUAX_STATE(L); + T* self = state.GetLuaUserdata(1); + if (self) + { + char buf[1024] = {0}; + const char* fmt = "%p <%s>"; + cc8* classname = ""; + lua_getfield(state, 1, "GetClassName"); + if (state.IsType(-1, LUA_TFUNCTION)) + { + lua_pushvalue(L, 1); // userdata + state.Call(1, 1); // 派生类的GetClassName函数 + classname = state.GetValue(-1, ""); + } + else + { + classname = T::GetLuaxClassName(); + } + sprintf(buf, fmt, self, classname); + lua_pushstring(L, buf); + return 1; + } return 0; } template int LuaxClass::l_ExtendFactory(lua_State* L) { + + + return 0; + } + + template + int LuaxClass::l_ExtendSingleton(lua_State* L) + { + + return 0; } @@ -274,9 +392,33 @@ namespace Luax int LuaxClass::l_GetInterfaceTable(lua_State* L) { LUAX_STATE(L); - assert(mInterfaceTable); - mInterfaceTable.PushRef(state); - return 0; + if (!mInterfaceTable) + lua_pushnil(L); + else + mInterfaceTable.PushRef(state); + return 1; + } + + template + int LuaxClass::l_GetClass(lua_State* L) + { + LUAX_STATE(L); + if (!mClassTable) + lua_pushnil(L); + else + mClassTable.PushRef(state); + return 1; + } + + template + int LuaxClass::l_GetRefTable(lua_State* L) + { + LUAX_STATE(L); + T* self = state.GetLuaUserdata(1); + bool success = self->PushLuaxRefTable(state); + if (!success) + lua_pushnil(L); + return 1; } template LuaxStrongRef LuaxClass::mInterfaceTable; // interface table -- cgit v1.1-26-g67d0