namespace Luax { //---------------------------------------------------------------------------------------------------------------- // 接口 /// /// 对不同类型,通过调用GetLuaClassName获得类型名,如果是派生类,GetClassName会被覆盖,指向luax_c_getupvalue。 /// template int LuaxNativeClass::l_GetClassName(lua_State* L) { LUAX_SETUP(L, "*"); cc8* type = T::GetLuaxClassName(); state.Push(type); return 1; } //---------------------------------------------------------------------------------------------------------------- /// /// 注册工厂和单例共有的类成员 /// template void LuaxNativeClass::RegisterLuaxClass(LuaxState& state) { luaL_Reg regTable[] = { { "GetClassName", l_GetClassName }, { NULL, NULL } }; state.RegisterMethods(regTable); } /// /// 工厂类的成员,注册在class table /// template void LuaxNativeClass::RegisterLuaxFactoryClass(LuaxState& state) { luaL_Reg regTable[] = { { "GetClass", l_GetClass }, { "GetRefTable", l_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() { } template LuaxNativeClass::~LuaxNativeClass() { } template template void LuaxNativeClass::LuaRetain(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::LuaRelease(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 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 } } } template bool LuaxNativeClass::PushLuaxUserdata(LuaxState& state) { assert(!T::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; } } } state.SetTop(top); lua_pushnil(state); return false; } template bool LuaxNativeClass::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; } /// /// 创建userdata,并以此添加ref table,member table和class table。 /// ref table 是kv强引用table,保存对其他userdata的引用计数(通过userdata作为key,计数为value),以及成员引用 /// member table 保存lua创建的实例的成员 /// class table 所有本类型的实例共有的函数表 /// template void LuaxNativeClass::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中创建的对象成员都保存在这里 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 注册 __gc 和 __tostring lua_pushcfunction(state, l___gc); lua_setfield(state, refTable, "__gc"); lua_pushcfunction(state, l___tostring); lua_setfield(state, refTable, "__tostring"); // 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); } /// /// 成员引用管理 /// template void LuaxNativeClass::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 LuaxNativeClass::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 LuaxNativeClass::ClearMemberRef(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::l___gc(lua_State* L) { LUAX_SETUP(L, "U"); return 0; } /// /// 输出格式如下: /// 地址 类名 /// template int LuaxNativeClass::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 LuaxNativeClass::l_ExtendFactory(lua_State* L) { return 0; } template int LuaxNativeClass::l_ExtendSingleton(lua_State* L) { return 0; } template int LuaxNativeClass::l_GetClass(lua_State* L) { LUAX_STATE(L); if (!mClassTable) lua_pushnil(L); else mClassTable.PushRef(state); return 1; } template int LuaxNativeClass::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 LuaxNativeClass::mClassTable; // class table template LuaxStrongRef LuaxNativeClass::mSingletonRefTable; // 单例 }