namespace Luax { //---------------------------------------------------------------------------------------------------------------- // 接口 /// /// 对不同类型,通过调用GetLuaClassName获得类型名 /// template int LuaxClass::l_GetClassName(lua_State* L) { LUAX_SETUP(L, "*"); cc8* type = T::GetLuaxClassName(); state.Push(type); return 1; } //---------------------------------------------------------------------------------------------------------------- /// /// 注册工厂和单例共有的类成员 /// template void LuaxClass::RegisterLuaxClass(LuaxState& state) { luaL_Reg regTable[] = { { "GetClassName", l_GetClassName }, { NULL, NULL } }; state.RegisterMethods(regTable); } /// /// 工厂类的成员,注册在class table /// template void LuaxClass::RegisterLuaxFactoryClass(LuaxState& state) { luaL_Reg regTable[] = { { "GetInterfaceTable", l_GetInterfaceTable }, { NULL, NULL } }; state.RegisterMethods(regTable); } /// /// 工厂实例的成员,注册在interface table /// template void LuaxClass::RegisterLuaxInterface(LuaxState& state) { luaL_Reg regTable[] = { { "__gc", l___gc }, { NULL, NULL } }; state.RegisterMethods(regTable); } /// /// 单例类的成员,注册在class table /// template void LuaxClass::RegisterLuaxSingletonClass(LuaxState& state) { luaL_Reg regTable[] = { { NULL, NULL } }; state.RegisterMethods(regTable); } template void LuaxClass::PushLuaxInterfaceTable(LuaxState& state) { assert(mInterfaceTable); mInterfaceTable.PushRef(state); } template void LuaxClass::PushLuaxClassTable(LuaxState& state) { assert(mClassTable); mClassTable.PushRef(state); } template void LuaxClass::SetLuaxInterfaceTableRef(LuaxState& state, int idx) { mInterfaceTable.SetRef(state, idx); } template void LuaxClass::SetLuaxClassTableRef(LuaxState& state, int idx) { mClassTable.SetRef(state, idx); } template LuaxClass::LuaxClass() : mRC(1) // 构造时默认有一个引用 , mSafer(false) { } template LuaxClass::~LuaxClass() { assert(mSafer); } template void LuaxClass::Retain() { ++mRC; } template void LuaxClass::Release() { if (--mRC <= 0) { mSafer = true; // 打开析构safer delete this; } } template bool LuaxClass::PushLuaxUserdata(LuaxState& state) { assert(!T::IsLuaxClassSingleton()); if (!mUserdata) { BindToLua(state); return true; } return mUserdata.PushRef(state); } template bool LuaxClass::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; } } } state.SetTop(top); lua_pushnil(state); return false; } template bool LuaxClass::PushLuaxRefTable(LuaxState& state) { // Singleton if (T::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; } template void LuaxClass::BindToLua(LuaxState& state) { // 单例不能绑定userdata assert(!T::IsLuaxClassSingleton()); assert(!mUserdata); // 创建userdata并留在栈顶 state.PushPtrUserData(this); lua_newtable(state); // ref table,无法在lua处访问,用来管理C对象的生命周期 lua_newtable(state); // member table,lua中创建的对象成员都保存在这里 PushLuaxInterfaceTable(state); // interface table,如果member table里没有这个成员,在interface table里找。 // stack: // -1: interface table // -2: member table // -3: ref table // -4: userdata int top = state.GetTop(); int memberTable = top - 1; int refTable = top - 2; // 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 lua_pushvalue(state, memberTable); lua_setfield(state, refTable, "__index"); lua_pushvalue(state, memberTable); lua_setfield(state, refTable, "__newindex"); // 设置元表 lua_setmetatable(state, -2); // interface 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); } //-------------------------------------------------------------------------------------------------------------- /// /// 释放工厂创建的实例 /// template int LuaxClass::l___gc(lua_State* L) { LUAX_SETUP(L, "U"); return 0; } template int LuaxClass::l___tostring(lua_State* L) { return 0; } template int LuaxClass::l_ExtendFactory(lua_State* L) { return 0; } template int LuaxClass::l_GetInterfaceTable(lua_State* L) { LUAX_STATE(L); assert(mInterfaceTable); mInterfaceTable.PushRef(state); return 0; } template LuaxStrongRef LuaxClass::mInterfaceTable; // interface table template LuaxStrongRef LuaxClass::mClassTable; // class table template LuaxStrongRef LuaxClass::mSingletonRefTable; // 单例 }