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[] = { { "GetClass", l_GetClass }, { "GetClassName", l_GetClassName }, { NULL, NULL } }; state.RegisterMethods(regTable); } /// /// 工厂类的成员,注册在class table /// template void LuaxNativeClass::RegisterLuaxFactoryClass(LuaxState& state) { luaL_Reg regTable[] = { { "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 注册 __tostring 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_pushcfunction(state, l___gc); lua_setfield(state, refTable, "__gc"); // 设置元表 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"); T* self = state.GetLuaUserdata(1); delete self; return 0; } /// /// 输出格式如下: /// 地址 类名 /// template int LuaxNativeClass::l___tostring(lua_State* L) { // params: // 1: userdata LUAX_STATE(L); T* self = state.GetLuaUserdata(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 = T::GetLuaxClassName(); } lua_pushfstring(L, "%s: %p", classname, self); return 1; } return 0; } #ifdef LUAX_ENABLE_NATIVE_EXTEND /// /// 派生出子类,在lua里对派生类的成员和行为进行重新设计,但是保证了userdata的统一。Native class的派生提供Ctor支持,在 /// native实体创建后可以使用Ctor进行初始化,派生类拥有和基类一样的New参数列表,且native对象是一样的类型。 /// template int LuaxNativeClass::l_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, l_ExtendFactory, 1); lua_setfield(L, -2, "Extend"); // .New() lua_pushvalue(L, inheritClass); lua_getfield(L, baseClass, "New"); lua_pushcclosure(L, 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::l_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, 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 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 int LuaxNativeClass::l_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); // 尝试调用Ctor函数 lua_getfield(L, lua_upvalueindex(1), "Ctor"); 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; // 单例 }