From bad78945ceba425f6a80e3b8dca2414d592970eb Mon Sep 17 00:00:00 2001 From: chai Date: Fri, 2 Aug 2019 20:51:00 +0800 Subject: =?UTF-8?q?*=E4=BF=AE=E6=94=B9=E6=96=87=E4=BB=B6=E5=90=8D=E6=A0=BC?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/external/Luax/luax.h | 4 +- source/external/Luax/luax_class.inc | 637 ++++++++++++++++++++++++++++++++++++ source/external/Luax/luax_class.inl | 637 ------------------------------------ source/external/Luax/luax_state.inc | 180 ++++++++++ source/external/Luax/luax_state.inl | 180 ---------- 5 files changed, 819 insertions(+), 819 deletions(-) create mode 100644 source/external/Luax/luax_class.inc delete mode 100644 source/external/Luax/luax_class.inl create mode 100644 source/external/Luax/luax_state.inc delete mode 100644 source/external/Luax/luax_state.inl (limited to 'source/external') diff --git a/source/external/Luax/luax.h b/source/external/Luax/luax.h index 7a0dcd6..1980f41 100644 --- a/source/external/Luax/luax.h +++ b/source/external/Luax/luax.h @@ -12,7 +12,7 @@ #include "luax_enum.h" #include "luax_class.hpp" #include "luax_memberref.h" -#include "luax_class.inl" -#include "luax_state.inl" +#include "luax_class.inc" +#include "luax_state.inc" #endif \ No newline at end of file diff --git a/source/external/Luax/luax_class.inc b/source/external/Luax/luax_class.inc new file mode 100644 index 0000000..1d6a89f --- /dev/null +++ b/source/external/Luax/luax_class.inc @@ -0,0 +1,637 @@ +namespace Luax +{ + + //--------------------------------------------------------------------------------// + + /// + /// 对不同类型,通过调用GetLuaClassName获得类型名,如果是派生类,GetClassName会被覆盖,指向luax_c_getupvalue。 + /// + template + int LuaxNativeClass::_GetClassName(lua_State* L) + { + LUAX_SETUP(L, "*"); + + cc8* type = TYPE::GetLuaxClassName(); + state.Push(type); + return 1; + } + + //--------------------------------------------------------------------------------// + + /// + /// 注册工厂和单例共有的类成员 + /// + template + void LuaxNativeClass::RegisterLuaxClassShared(LuaxState& state) + { + luaL_Reg regTable[] = { + { "GetClass", _GetClass }, + { "GetClassName", _GetClassName }, + { NULL, NULL } + }; + + state.RegisterMethods(regTable); + } + + /// + /// 工厂类的成员,注册在class table + /// + template + void LuaxNativeClass::RegisterLuaxFactoryClass(LuaxState& state) + { + luaL_Reg regTable[] = { + { "GetRefTable", _GetRefTable }, + { NULL, NULL } + }; + + state.RegisterMethods(regTable); + } + + /// + /// 单例类的成员,注册在class table + /// + template + void LuaxNativeClass::RegisterLuaxSingletonClass(LuaxState& state) + { + luaL_Reg regTable[] = { + { NULL, NULL } + }; + + state.RegisterMethods(regTable); + } + + template + void LuaxNativeClass::PushLuaxClassTable(LuaxState& state) + { + assert(mClassTable); + + mClassTable.PushRef(state); + } + + template + void LuaxNativeClass::SetLuaxClassTableRef(LuaxState& state, int idx) + { + mClassTable.SetRef(state, idx); + } + + template + LuaxNativeClass::LuaxNativeClass() + : mWatchDog() +#if LUAX_PROFILER + , mSafer(false) +#endif + { + } + + template + LuaxNativeClass::~LuaxNativeClass() + { + } + +#if LUAX_PROFILER + template + void LuaxNativeClass::operator delete(void* pdead, size_t size) + { + if (pdead == nullptr) + return; + // 堆上创建的实例必须使用Release释放。 + TYPE* p = static_cast(pdead); + assert(p->mSafer); + ::operator delete(pdead, size); + } +#endif + + template + void LuaxNativeClass::Retain() + { + ++mWatchDog.mNativeRef; + } + + template + void LuaxNativeClass::Release() + { + if (mWatchDog.mNativeRef > 0) + --mWatchDog.mNativeRef; + if (mWatchDog) + { +#if LUAX_PROFILER + mSafer = true; +#endif + delete this; + } + } + + template + template + void LuaxNativeClass::LuaxRetain(LuaxState& state, U* userdata) + { + 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 + template + void LuaxNativeClass::LuaxRelease(LuaxState& state, U* userdata) + { + 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 + + // no such reference + if (count == 0) + { + state.Pop(2); // userdata, reftable + 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 + + state.Pop(1); // reftable + return; + } + state.Pop(2); // nil, reftable + return; + } + } + + template + bool LuaxNativeClass::PushLuaxUserdata(LuaxState& state) + { + assert(!TYPE::IsLuaxClassSingleton()); + if (!mUserdata) + { + BindToLua(state); + return true; + } + return mUserdata.PushRef(state); + } + + template + bool LuaxNativeClass::PushLuaxMemberTable(LuaxState& state) + { + int top = state.GetTop(); + if (this->PushLuaxUserdata(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 LuaxNativeClass::PushLuaxRefTable(LuaxState& state) + { + // Singleton + if (TYPE::IsLuaxClassSingleton()) + { + 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->PushLuaxUserdata(state)) + { + if (lua_getmetatable(state, -1)) + { + lua_replace(state, -2); + return true; + } + } + } + return false; + } + + /// + /// 创建userdata,并以此添加ref table,member table和class table。 + /// ref table 是kv强引用table,保存对其他userdata的引用计数(通过userdata作为key, + /// 计数为value),以及成员引用 + /// member table 保存lua创建的实例的成员 + /// class table 所有本类型的实例共有的函数表 + /// + /// BindToLua只会在第一次注册给Lua虚拟机时调用。 + /// + template + void LuaxNativeClass::BindToLua(LuaxState& state) + { + // 单例不能绑定userdata + assert(!TYPE::IsLuaxClassSingleton()); + 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中创建的对象成员都保存在这里 + PushLuaxClassTable(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"); + + // 设置元表 + 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的弱引用,方便通过PushLuaUserdata方法返回lua对象 + mUserdata.SetRef(state, -1); + assert(mUserdata); + + // 增加一个虚拟机引用,在GC时-1 + ++mWatchDog.mVMRef; +#if LUAX_PROFILER + mRefVMs.insert(state.GetVM()); +#endif + } + + /// + /// 成员引用管理 + /// + template + void LuaxNativeClass::SetLuaxMemberRef(LuaxState& state, LuaxMemberRef& memRef, int idx) + { + ClearLuaxMemberRef(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 LuaxNativeClass::PushLuaxMemberRef(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 + bool LuaxNativeClass::PushLuaxMemberRef(LuaxState& state, int refID) + { + if (PushLuaxRefTable(state)) + { + lua_rawgeti(state, -1, refID); + lua_replace(state, -2); // ref table + if (lua_isnil(state, -1)) + goto failed; + return true; + } + lua_pushnil(state); + failed: + return false; + } + + template + void LuaxNativeClass::ClearLuaxMemberRef(LuaxState& state, LuaxMemberRef& memRef) + { + if (memRef) + { + if (PushLuaxRefTable(state)) + { + luaL_unref(state, -1, memRef.refID); + state.Pop(); // ref table + } + memRef.refID = LUA_NOREF; + } + } + + //--------------------------------------------------------------------------------// + + /// + /// 释放工厂创建的实例 + /// + template + int LuaxNativeClass::__gc(lua_State* L) + { + LUAX_STATE(L); + + TYPE* self = state.GetUserdata(1); + assert(self); + +#if LUAX_PROFILER + std::cout << "Luax: GC<" << TYPE::GetLuaxClassName() << ">\n"; +#endif + + if(self->mWatchDog.mVMRef > 0) + --self->mWatchDog.mVMRef; + + self->Release(); + + return 0; + } + + /// + /// 输出格式如下: + /// 地址 类名 + /// + template + int LuaxNativeClass::__tostring(lua_State* L) + { + // params: + // 1: userdata + + LUAX_STATE(L); + TYPE* self = state.GetUserdata(1); + if (self) + { + 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 = TYPE::GetLuaxClassName(); + } + lua_pushfstring(L, "%s: %p", classname, self); + return 1; + } + return 0; + } + +#if LUAX_ENABLE_NATIVE_EXTEND + /// + /// 派生出子类,在lua里对派生类的成员和行为进行重新设计,但是保证了userdata的统一。Native class的派生提供__init支持,在 + /// native实体创建后可以使用__init进行初始化,派生类拥有和基类一样的New参数列表,且native对象是一样的类型。 + /// + template + int LuaxNativeClass::_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 LuaxNativeClass::_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; + } +#endif /*LUAX_ENABLE_NATIVE_EXTEND*/ + + template + int LuaxNativeClass::_GetClass(lua_State* L) + { + LUAX_STATE(L); + if (!mClassTable) + lua_pushnil(L); + else + mClassTable.PushRef(state); + return 1; + } + + template + int LuaxNativeClass::_GetRefTable(lua_State* L) + { + LUAX_STATE(L); + TYPE* self = state.GetUserdata(1); + bool success = self->PushLuaxRefTable(state); + if (!success) + lua_pushnil(L); + return 1; + } + + template + int LuaxNativeClass::_New(lua_State* L) + { + LUAX_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; + } + + template LuaxStrongRef LuaxNativeClass::mClassTable; // class table + template LuaxStrongRef LuaxNativeClass::mSingletonRefTable; // 单例 + +} \ No newline at end of file diff --git a/source/external/Luax/luax_class.inl b/source/external/Luax/luax_class.inl deleted file mode 100644 index 1d6a89f..0000000 --- a/source/external/Luax/luax_class.inl +++ /dev/null @@ -1,637 +0,0 @@ -namespace Luax -{ - - //--------------------------------------------------------------------------------// - - /// - /// 对不同类型,通过调用GetLuaClassName获得类型名,如果是派生类,GetClassName会被覆盖,指向luax_c_getupvalue。 - /// - template - int LuaxNativeClass::_GetClassName(lua_State* L) - { - LUAX_SETUP(L, "*"); - - cc8* type = TYPE::GetLuaxClassName(); - state.Push(type); - return 1; - } - - //--------------------------------------------------------------------------------// - - /// - /// 注册工厂和单例共有的类成员 - /// - template - void LuaxNativeClass::RegisterLuaxClassShared(LuaxState& state) - { - luaL_Reg regTable[] = { - { "GetClass", _GetClass }, - { "GetClassName", _GetClassName }, - { NULL, NULL } - }; - - state.RegisterMethods(regTable); - } - - /// - /// 工厂类的成员,注册在class table - /// - template - void LuaxNativeClass::RegisterLuaxFactoryClass(LuaxState& state) - { - luaL_Reg regTable[] = { - { "GetRefTable", _GetRefTable }, - { NULL, NULL } - }; - - state.RegisterMethods(regTable); - } - - /// - /// 单例类的成员,注册在class table - /// - template - void LuaxNativeClass::RegisterLuaxSingletonClass(LuaxState& state) - { - luaL_Reg regTable[] = { - { NULL, NULL } - }; - - state.RegisterMethods(regTable); - } - - template - void LuaxNativeClass::PushLuaxClassTable(LuaxState& state) - { - assert(mClassTable); - - mClassTable.PushRef(state); - } - - template - void LuaxNativeClass::SetLuaxClassTableRef(LuaxState& state, int idx) - { - mClassTable.SetRef(state, idx); - } - - template - LuaxNativeClass::LuaxNativeClass() - : mWatchDog() -#if LUAX_PROFILER - , mSafer(false) -#endif - { - } - - template - LuaxNativeClass::~LuaxNativeClass() - { - } - -#if LUAX_PROFILER - template - void LuaxNativeClass::operator delete(void* pdead, size_t size) - { - if (pdead == nullptr) - return; - // 堆上创建的实例必须使用Release释放。 - TYPE* p = static_cast(pdead); - assert(p->mSafer); - ::operator delete(pdead, size); - } -#endif - - template - void LuaxNativeClass::Retain() - { - ++mWatchDog.mNativeRef; - } - - template - void LuaxNativeClass::Release() - { - if (mWatchDog.mNativeRef > 0) - --mWatchDog.mNativeRef; - if (mWatchDog) - { -#if LUAX_PROFILER - mSafer = true; -#endif - delete this; - } - } - - template - template - void LuaxNativeClass::LuaxRetain(LuaxState& state, U* userdata) - { - 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 - template - void LuaxNativeClass::LuaxRelease(LuaxState& state, U* userdata) - { - 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 - - // no such reference - if (count == 0) - { - state.Pop(2); // userdata, reftable - 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 - - state.Pop(1); // reftable - return; - } - state.Pop(2); // nil, reftable - return; - } - } - - template - bool LuaxNativeClass::PushLuaxUserdata(LuaxState& state) - { - assert(!TYPE::IsLuaxClassSingleton()); - if (!mUserdata) - { - BindToLua(state); - return true; - } - return mUserdata.PushRef(state); - } - - template - bool LuaxNativeClass::PushLuaxMemberTable(LuaxState& state) - { - int top = state.GetTop(); - if (this->PushLuaxUserdata(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 LuaxNativeClass::PushLuaxRefTable(LuaxState& state) - { - // Singleton - if (TYPE::IsLuaxClassSingleton()) - { - 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->PushLuaxUserdata(state)) - { - if (lua_getmetatable(state, -1)) - { - lua_replace(state, -2); - return true; - } - } - } - return false; - } - - /// - /// 创建userdata,并以此添加ref table,member table和class table。 - /// ref table 是kv强引用table,保存对其他userdata的引用计数(通过userdata作为key, - /// 计数为value),以及成员引用 - /// member table 保存lua创建的实例的成员 - /// class table 所有本类型的实例共有的函数表 - /// - /// BindToLua只会在第一次注册给Lua虚拟机时调用。 - /// - template - void LuaxNativeClass::BindToLua(LuaxState& state) - { - // 单例不能绑定userdata - assert(!TYPE::IsLuaxClassSingleton()); - 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中创建的对象成员都保存在这里 - PushLuaxClassTable(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"); - - // 设置元表 - 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的弱引用,方便通过PushLuaUserdata方法返回lua对象 - mUserdata.SetRef(state, -1); - assert(mUserdata); - - // 增加一个虚拟机引用,在GC时-1 - ++mWatchDog.mVMRef; -#if LUAX_PROFILER - mRefVMs.insert(state.GetVM()); -#endif - } - - /// - /// 成员引用管理 - /// - template - void LuaxNativeClass::SetLuaxMemberRef(LuaxState& state, LuaxMemberRef& memRef, int idx) - { - ClearLuaxMemberRef(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 LuaxNativeClass::PushLuaxMemberRef(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 - bool LuaxNativeClass::PushLuaxMemberRef(LuaxState& state, int refID) - { - if (PushLuaxRefTable(state)) - { - lua_rawgeti(state, -1, refID); - lua_replace(state, -2); // ref table - if (lua_isnil(state, -1)) - goto failed; - return true; - } - lua_pushnil(state); - failed: - return false; - } - - template - void LuaxNativeClass::ClearLuaxMemberRef(LuaxState& state, LuaxMemberRef& memRef) - { - if (memRef) - { - if (PushLuaxRefTable(state)) - { - luaL_unref(state, -1, memRef.refID); - state.Pop(); // ref table - } - memRef.refID = LUA_NOREF; - } - } - - //--------------------------------------------------------------------------------// - - /// - /// 释放工厂创建的实例 - /// - template - int LuaxNativeClass::__gc(lua_State* L) - { - LUAX_STATE(L); - - TYPE* self = state.GetUserdata(1); - assert(self); - -#if LUAX_PROFILER - std::cout << "Luax: GC<" << TYPE::GetLuaxClassName() << ">\n"; -#endif - - if(self->mWatchDog.mVMRef > 0) - --self->mWatchDog.mVMRef; - - self->Release(); - - return 0; - } - - /// - /// 输出格式如下: - /// 地址 类名 - /// - template - int LuaxNativeClass::__tostring(lua_State* L) - { - // params: - // 1: userdata - - LUAX_STATE(L); - TYPE* self = state.GetUserdata(1); - if (self) - { - 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 = TYPE::GetLuaxClassName(); - } - lua_pushfstring(L, "%s: %p", classname, self); - return 1; - } - return 0; - } - -#if LUAX_ENABLE_NATIVE_EXTEND - /// - /// 派生出子类,在lua里对派生类的成员和行为进行重新设计,但是保证了userdata的统一。Native class的派生提供__init支持,在 - /// native实体创建后可以使用__init进行初始化,派生类拥有和基类一样的New参数列表,且native对象是一样的类型。 - /// - template - int LuaxNativeClass::_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 LuaxNativeClass::_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; - } -#endif /*LUAX_ENABLE_NATIVE_EXTEND*/ - - template - int LuaxNativeClass::_GetClass(lua_State* L) - { - LUAX_STATE(L); - if (!mClassTable) - lua_pushnil(L); - else - mClassTable.PushRef(state); - return 1; - } - - template - int LuaxNativeClass::_GetRefTable(lua_State* L) - { - LUAX_STATE(L); - TYPE* self = state.GetUserdata(1); - bool success = self->PushLuaxRefTable(state); - if (!success) - lua_pushnil(L); - return 1; - } - - template - int LuaxNativeClass::_New(lua_State* L) - { - LUAX_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; - } - - template LuaxStrongRef LuaxNativeClass::mClassTable; // class table - template LuaxStrongRef LuaxNativeClass::mSingletonRefTable; // 单例 - -} \ No newline at end of file diff --git a/source/external/Luax/luax_state.inc b/source/external/Luax/luax_state.inc new file mode 100644 index 0000000..6671bb5 --- /dev/null +++ b/source/external/Luax/luax_state.inc @@ -0,0 +1,180 @@ +namespace Luax +{ + + /// + /// 注册工厂,注册class table,以type name为键设置在名称空间上。在注册阶段不会设置元表,等到New方法调用的时候才会。 + /// + template + void LuaxState::RegisterFactory() + { + cc8* type = TYPE::GetLuaxFactoryName(); + + lua_State* L = mState; + LuaxState& state = *this; + + int top = lua_gettop(L); // namespace table + assert(lua_istable(L, top)); + + // class table + lua_newtable(L); + TYPE::RegisterLuaxClassShared(state); + TYPE::RegisterLuaxFactoryClass(state); + TYPE::RegisterLuaxClass(state); + + // 检测TYPE里面是否没有注册必须的方法 +#define _assertmethod(I, NAME) \ + GetField(I, NAME); \ + assert(IsType(-1, LUA_TFUNCTION)); \ + Pop(); + + //_assertmethod(-1, "New"); + +#undef _assertmethod + +#if LUAX_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::SetLuaxClassTableRef(state, -1); + + SetField(top, type); + + // reset top + lua_settop(L, top); + + // 后处理 + TYPE::RegisterLuaxPostprocess(state); + } + + /// + /// Singleton + /// + template + void LuaxState::RegisterSingleton() + { + lua_State* L = mState; + LuaxState& state = *this; + + int top = lua_gettop(L); // namespace table + assert(lua_istable(L, top)); + + // class table. + lua_newtable(L); + TYPE::RegisterLuaxClassShared(state); + TYPE::RegisterLuaxSingletonClass(state); + TYPE::RegisterLuaxClass(state); + + TYPE::SetLuaxClassTableRef(state, -1); + + lua_pushvalue(state, -1); + lua_setfield(state, -2, "__index"); + +#if LUAX_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::GetLuaxSingletonName(); + SetField(top, type); + + // reset top + lua_settop(L, top); + + // 后处理 + TYPE::RegisterLuaxPostprocess(state); + } + + template + void LuaxState::SetField(int idx, cc8* key, TYPE value) + { + if (IsTableOrUserdata(idx)) + { + idx = AbsIndex(idx); + this->Push(value); + lua_setfield(mState, idx, key); + } + } + + template + void LuaxState::SetFieldByIndex(int idx, int key, TYPE value) + { + if (IsTableOrUserdata(idx)) + { + idx = AbsIndex(idx); + this->Push(value); + lua_rawseti(mState, idx, key); + } + } + + template + TYPE LuaxState::GetField(int idx, cc8* key, TYPE value) + { + GetField(idx, key); + TYPE result = GetValue < TYPE >(-1, value); + this->Pop(); + + return result; + } + + template + TYPE LuaxState::GetField(int idx, int key, TYPE value) + { + GetField(idx, key); + TYPE result = GetValue < TYPE >(-1, value); + Pop(); + + return result; + } + + template + TYPE* LuaxState::GetUserdata(int idx) + { + void* p = nullptr; + + if (IsType(idx, LUA_TUSERDATA)) + { + p = *(void**)lua_touserdata(mState, idx); + } + + return static_cast(p); + } + + template + TYPE* LuaxState::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::PushLuaxClassTable(*this); // target class table + if (lua_rawequal(mState, -1, -2)) + { + Pop(4); // ref\member\class\target class + TYPE* udata = GetUserdata(idx); + return udata; // userdata + } + Pop(2); // target class table\class table + } + Pop(1); // member table + } + Pop(1); // ref table + } + } + luaL_typerror(mState, idx, TYPE::GetLuaxClassName()); + return nullptr; + } + +} \ No newline at end of file diff --git a/source/external/Luax/luax_state.inl b/source/external/Luax/luax_state.inl deleted file mode 100644 index 6671bb5..0000000 --- a/source/external/Luax/luax_state.inl +++ /dev/null @@ -1,180 +0,0 @@ -namespace Luax -{ - - /// - /// 注册工厂,注册class table,以type name为键设置在名称空间上。在注册阶段不会设置元表,等到New方法调用的时候才会。 - /// - template - void LuaxState::RegisterFactory() - { - cc8* type = TYPE::GetLuaxFactoryName(); - - lua_State* L = mState; - LuaxState& state = *this; - - int top = lua_gettop(L); // namespace table - assert(lua_istable(L, top)); - - // class table - lua_newtable(L); - TYPE::RegisterLuaxClassShared(state); - TYPE::RegisterLuaxFactoryClass(state); - TYPE::RegisterLuaxClass(state); - - // 检测TYPE里面是否没有注册必须的方法 -#define _assertmethod(I, NAME) \ - GetField(I, NAME); \ - assert(IsType(-1, LUA_TFUNCTION)); \ - Pop(); - - //_assertmethod(-1, "New"); - -#undef _assertmethod - -#if LUAX_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::SetLuaxClassTableRef(state, -1); - - SetField(top, type); - - // reset top - lua_settop(L, top); - - // 后处理 - TYPE::RegisterLuaxPostprocess(state); - } - - /// - /// Singleton - /// - template - void LuaxState::RegisterSingleton() - { - lua_State* L = mState; - LuaxState& state = *this; - - int top = lua_gettop(L); // namespace table - assert(lua_istable(L, top)); - - // class table. - lua_newtable(L); - TYPE::RegisterLuaxClassShared(state); - TYPE::RegisterLuaxSingletonClass(state); - TYPE::RegisterLuaxClass(state); - - TYPE::SetLuaxClassTableRef(state, -1); - - lua_pushvalue(state, -1); - lua_setfield(state, -2, "__index"); - -#if LUAX_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::GetLuaxSingletonName(); - SetField(top, type); - - // reset top - lua_settop(L, top); - - // 后处理 - TYPE::RegisterLuaxPostprocess(state); - } - - template - void LuaxState::SetField(int idx, cc8* key, TYPE value) - { - if (IsTableOrUserdata(idx)) - { - idx = AbsIndex(idx); - this->Push(value); - lua_setfield(mState, idx, key); - } - } - - template - void LuaxState::SetFieldByIndex(int idx, int key, TYPE value) - { - if (IsTableOrUserdata(idx)) - { - idx = AbsIndex(idx); - this->Push(value); - lua_rawseti(mState, idx, key); - } - } - - template - TYPE LuaxState::GetField(int idx, cc8* key, TYPE value) - { - GetField(idx, key); - TYPE result = GetValue < TYPE >(-1, value); - this->Pop(); - - return result; - } - - template - TYPE LuaxState::GetField(int idx, int key, TYPE value) - { - GetField(idx, key); - TYPE result = GetValue < TYPE >(-1, value); - Pop(); - - return result; - } - - template - TYPE* LuaxState::GetUserdata(int idx) - { - void* p = nullptr; - - if (IsType(idx, LUA_TUSERDATA)) - { - p = *(void**)lua_touserdata(mState, idx); - } - - return static_cast(p); - } - - template - TYPE* LuaxState::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::PushLuaxClassTable(*this); // target class table - if (lua_rawequal(mState, -1, -2)) - { - Pop(4); // ref\member\class\target class - TYPE* udata = GetUserdata(idx); - return udata; // userdata - } - Pop(2); // target class table\class table - } - Pop(1); // member table - } - Pop(1); // ref table - } - } - luaL_typerror(mState, idx, TYPE::GetLuaxClassName()); - return nullptr; - } - -} \ No newline at end of file -- cgit v1.1-26-g67d0