summaryrefslogtreecommitdiff
path: root/Runtime/Lua
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-10-22 09:23:08 +0800
committerchai <chaifix@163.com>2021-10-22 09:23:08 +0800
commit1f18d2afec632aa9361079ca3bcb5a7f2d73db3a (patch)
treedab695a32735d1f19ae74ea7e7d094371531dde8 /Runtime/Lua
parent998a13b08c43b0813d1d4d38692ea7f8bd31c936 (diff)
*misc
Diffstat (limited to 'Runtime/Lua')
-rw-r--r--Runtime/Lua/LuaBind/LuaBindClass.hpp630
-rw-r--r--Runtime/Lua/LuaBind/LuaBindClass.inc628
-rw-r--r--Runtime/Lua/LuaBind/LuaBindRef.cpp4
-rw-r--r--Runtime/Lua/LuaBind/LuaBindRef.h25
-rw-r--r--Runtime/Lua/LuaBind/LuaBindRefTable.h10
-rw-r--r--Runtime/Lua/LuaBind/LuaBindState.h5
6 files changed, 649 insertions, 653 deletions
diff --git a/Runtime/Lua/LuaBind/LuaBindClass.hpp b/Runtime/Lua/LuaBind/LuaBindClass.hpp
index 2bf1451..154a4ce 100644
--- a/Runtime/Lua/LuaBind/LuaBindClass.hpp
+++ b/Runtime/Lua/LuaBind/LuaBindClass.hpp
@@ -203,6 +203,636 @@ namespace LuaBind
};
#endif
+ //--------------------------------------------------------------------------------//
+
+ //
+ // 对不同类型,通过调用GetLuaClassName获得类型名,如果是派生类,GetClassName会被覆盖,指向luax_c_getupvalue。
+ //
+ template<class TYPE, class BASE>
+ int NativeClass<TYPE, BASE>::_GetClassName(lua_State* L)
+ {
+ LUA_BIND_SETUP(L, "*");
+
+ cc8* type = TYPE::GetClassName();
+ state.Push(type);
+ return 1;
+ }
+
+ //--------------------------------------------------------------------------------//
+
+ //
+ // 注册工厂和单例共有的类成员
+ //
+ template<class TYPE, class BASE>
+ void NativeClass<TYPE, BASE>::RegisterClassShared(State& state)
+ {
+ luaL_Reg regTable[] = {
+ { "GetClass", _GetClass },
+ { "GetClassName", _GetClassName },
+ { NULL, NULL }
+ };
+
+ state.RegisterMethods(regTable);
+ }
+
+ //
+ // 工厂类的成员,注册在class table
+ //
+ template<class TYPE, class BASE>
+ void NativeClass<TYPE, BASE>::RegisterFactoryClass(State& state)
+ {
+ luaL_Reg regTable[] = {
+ { "GetRefTable", _GetRefTable },
+ { NULL, NULL }
+ };
+
+ state.RegisterMethods(regTable);
+ }
+
+ //
+ // 单例类的成员,注册在class table
+ //
+ template<class TYPE, class BASE>
+ void NativeClass<TYPE, BASE>::RegisterSingletonClass(State& state)
+ {
+ luaL_Reg regTable[] = {
+ { NULL, NULL }
+ };
+
+ state.RegisterMethods(regTable);
+ }
+
+ template<class TYPE, class BASE>
+ void NativeClass<TYPE, BASE>::PushClassTable(State& state)
+ {
+ assert(mClassTable);
+
+ mClassTable.PushRef(state);
+ }
+
+ template<class TYPE, class BASE>
+ void NativeClass<TYPE, BASE>::SetClassTableRef(State& state, int idx)
+ {
+ mClassTable.SetRef(state, idx);
+ }
+
+ template<class TYPE, class BASE>
+ NativeClass<TYPE, BASE>::NativeClass()
+ : mWatchDog()
+#if LUA_BIND_PROFILER
+ , mSafer(false)
+#endif
+ {
+ }
+
+ template<class TYPE, class BASE>
+ NativeClass<TYPE, BASE>::~NativeClass()
+ {
+ }
+
+#if LUA_BIND_PROFILER
+ template<class TYPE, class BASE>
+ void NativeClass<TYPE, BASE>::operator delete(void* pdead, size_t size)
+ {
+ if (pdead == nullptr)
+ return;
+ // 堆上创建的实例必须使用Release释放。
+ TYPE* p = static_cast<TYPE*>(pdead);
+ assert(p->mSafer);
+ ::operator delete(pdead, size);
+ }
+#endif
+
+ template<class TYPE, class BASE>
+ void NativeClass<TYPE, BASE>::Retain()
+ {
+ ++mWatchDog.mNativeRef;
+ }
+
+ template<class TYPE, class BASE>
+ void NativeClass<TYPE, BASE>::Release()
+ {
+ if (mWatchDog.mNativeRef > 0)
+ --mWatchDog.mNativeRef;
+ if (mWatchDog)
+ {
+#if LUA_BIND_PROFILER
+ mSafer = true;
+#endif
+ delete this;
+ }
+ }
+
+ template<class TYPE, class BASE>
+ template<typename U>
+ void NativeClass<TYPE, BASE>::Retain(State& state, U* userdata)
+ {
+ if (PushRefTable(state))
+ {
+ if (userdata->PushUserdata(state))
+ {
+ lua_pushvalue(state, -1); // copy the userdata
+ lua_gettable(state, -3); // get the count (or nil)
+ u32 count = state.GetValue<u32>(-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<class TYPE, class BASE>
+ template<typename U>
+ void NativeClass<TYPE, BASE>::Release(State& state, U* userdata)
+ {
+ if (PushRefTable(state))
+ {
+ if (userdata->PushUserdata(state))
+ {
+ lua_pushvalue(state, -1); // copy the userdata
+ lua_gettable(state, -3); // get the count (or nil)
+ u32 count = state.GetValue<u32>(-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<class TYPE, class BASE>
+ bool NativeClass<TYPE, BASE>::PushUserdata(State& state)
+ {
+ assert(!TYPE::IsClassSingleton());
+ if (!mUserdata)
+ {
+ BindToLua(state);
+ return true;
+ }
+ return mUserdata.PushRef(state);
+ }
+
+ template<class TYPE, class BASE>
+ bool NativeClass<TYPE, BASE>::PushMemberTable(State& state)
+ {
+ int top = state.GetTop();
+ if (this->PushUserdata(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<class TYPE, class BASE>
+ bool NativeClass<TYPE, BASE>::PushRefTable(State& state)
+ {
+ // Singleton
+ if (TYPE::IsClassSingleton())
+ {
+ 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->PushUserdata(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<class TYPE, class BASE>
+ void NativeClass<TYPE, BASE>::BindToLua(State& state)
+ {
+ // 单例不能绑定userdata
+ assert(!TYPE::IsClassSingleton());
+ assert(!mUserdata);
+
+ // 创建userdata并留在栈顶,注意地址要转换为TYPE*,直接用this可能会导致多重继承的类丧失多态。
+ // 如果直接传this进去,在多重继承情况下,是拿不到另一头的虚函数表的。所以这里需要将this
+ // 转换为整个对象的低地址,这样可以拿到另一个基类的虚函数表,通过另一个基类实现多态。
+ TYPE* p = static_cast<TYPE*>(this);
+ state.PushPtrUserdata(p);
+
+ lua_newtable(state); // ref table,无法在lua处访问,用来管理C对象的生命周期
+ lua_newtable(state); // member table,lua中创建的对象成员都保存在这里
+ PushClassTable(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 LUA_BIND_PROFILER
+ mRefVMs.insert(state.GetVM());
+#endif
+ }
+
+ //
+ // 成员引用管理
+ //
+ template<class TYPE, class BASE>
+ void NativeClass<TYPE, BASE>::SetMemberRef(State& state, MemberRef& memRef, int idx)
+ {
+ ClearMemberRef(state, memRef);
+ if (!lua_isnil(state, idx))
+ {
+ idx = state.AbsIndex(idx);
+ if (PushRefTable(state))
+ {
+ lua_pushvalue(state, idx);
+ memRef.refID = luaL_ref(state, -2);
+ state.Pop(); // ref table
+ }
+ }
+ }
+
+ template<class TYPE, class BASE>
+ bool NativeClass<TYPE, BASE>::PushMemberRef(State& state, MemberRef& memRef)
+ {
+ if (memRef)
+ {
+ if (PushRefTable(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<class TYPE, class BASE>
+ bool NativeClass<TYPE, BASE>::PushMemberRef(State& state, int refID)
+ {
+ if (PushRefTable(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<class TYPE, class BASE>
+ void NativeClass<TYPE, BASE>::ClearMemberRef(State& state, MemberRef& memRef)
+ {
+ if (memRef)
+ {
+ if (PushRefTable(state))
+ {
+ luaL_unref(state, -1, memRef.refID);
+ state.Pop(); // ref table
+ }
+ memRef.refID = LUA_NOREF;
+ }
+ }
+
+ //--------------------------------------------------------------------------------//
+
+ //
+ // 释放工厂创建的实例
+ //
+ template<class TYPE, class BASE>
+ int NativeClass<TYPE, BASE>::__gc(lua_State* L)
+ {
+ LUA_BIND_STATE(L);
+
+ TYPE* self = state.GetUserdata<TYPE>(1);
+ assert(self);
+
+#if LUA_BIND_PROFILER
+ std::cout << ": GC<" << TYPE::GetClassName() << ">\n";
+#endif
+
+ if (self->mWatchDog.mVMRef > 0)
+ --self->mWatchDog.mVMRef;
+
+ self->Release();
+
+ return 0;
+ }
+
+ //
+ // 输出格式如下:
+ // 地址 类名
+ //
+ template<class TYPE, class BASE>
+ int NativeClass<TYPE, BASE>::__tostring(lua_State* L)
+ {
+ // params:
+ // 1: userdata
+
+ LUA_BIND_STATE(L);
+ TYPE* self = state.GetUserdata<TYPE>(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<cc8*>(-1, "");
+ }
+ else
+ {
+ classname = TYPE::GetClassName();
+ }
+ lua_pushfstring(L, "%s: %p", classname, self);
+ return 1;
+ }
+ return 0;
+ }
+
+#if LUA_BIND_ENABLE_NATIVE_EXTEND
+ // 派生出子类,在lua里对派生类的成员和行为进行重新设计,但是保证了userdata的统一。Native class的派生提供__init支持,在
+ // native实体创建后可以使用__init进行初始化,派生类拥有和基类一样的New参数列表,且native对象是一样的类型。
+ template<class TYPE, class BASE>
+ int NativeClass<TYPE, BASE>::_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<class TYPE, class BASE>
+ int NativeClass<TYPE, BASE>::_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;
+ }
+
+ template<class TYPE, class BASE>
+ int NativeClass<TYPE, BASE>::_New(lua_State* L)
+ {
+ LUA_BIND_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;
+ }
+
+#endif /*LUA_BIND_ENABLE_NATIVE_EXTEND*/
+
+ template<class TYPE, class BASE>
+ int NativeClass<TYPE, BASE>::_GetClass(lua_State* L)
+ {
+ LUA_BIND_STATE(L);
+ if (!mClassTable)
+ lua_pushnil(L);
+ else
+ mClassTable.PushRef(state);
+ return 1;
+ }
+
+ template<class TYPE, class BASE>
+ int NativeClass<TYPE, BASE>::_GetRefTable(lua_State* L)
+ {
+ LUA_BIND_STATE(L);
+ TYPE* self = state.GetUserdata<TYPE>(1);
+ bool success = self->PushRefTable(state);
+ if (!success)
+ lua_pushnil(L);
+ return 1;
+ }
+
+ template<class TYPE, class BASE> StrongRef NativeClass<TYPE, BASE>::mClassTable; // class table
+ template<class TYPE, class BASE> StrongRef NativeClass<TYPE, BASE>::mSingletonRefTable; // 单例
+
+
+
}
#endif \ No newline at end of file
diff --git a/Runtime/Lua/LuaBind/LuaBindClass.inc b/Runtime/Lua/LuaBind/LuaBindClass.inc
index 05bd9c7..3c5990e 100644
--- a/Runtime/Lua/LuaBind/LuaBindClass.inc
+++ b/Runtime/Lua/LuaBind/LuaBindClass.inc
@@ -1,632 +1,4 @@
namespace LuaBind
{
- //--------------------------------------------------------------------------------//
-
- //
- // 对不同类型,通过调用GetLuaClassName获得类型名,如果是派生类,GetClassName会被覆盖,指向luax_c_getupvalue。
- //
- template<class TYPE, class BASE>
- int NativeClass<TYPE, BASE>::_GetClassName(lua_State* L)
- {
- LUA_BIND_SETUP(L, "*");
-
- cc8* type = TYPE::GetClassName();
- state.Push(type);
- return 1;
- }
-
- //--------------------------------------------------------------------------------//
-
- //
- // 注册工厂和单例共有的类成员
- //
- template<class TYPE, class BASE>
- void NativeClass<TYPE, BASE>::RegisterClassShared(State& state)
- {
- luaL_Reg regTable[] = {
- { "GetClass", _GetClass },
- { "GetClassName", _GetClassName },
- { NULL, NULL }
- };
-
- state.RegisterMethods(regTable);
- }
-
- //
- // 工厂类的成员,注册在class table
- //
- template<class TYPE, class BASE>
- void NativeClass<TYPE, BASE>::RegisterFactoryClass(State& state)
- {
- luaL_Reg regTable[] = {
- { "GetRefTable", _GetRefTable },
- { NULL, NULL }
- };
-
- state.RegisterMethods(regTable);
- }
-
- //
- // 单例类的成员,注册在class table
- //
- template<class TYPE, class BASE>
- void NativeClass<TYPE, BASE>::RegisterSingletonClass(State& state)
- {
- luaL_Reg regTable[] = {
- { NULL, NULL }
- };
-
- state.RegisterMethods(regTable);
- }
-
- template<class TYPE, class BASE>
- void NativeClass<TYPE, BASE>::PushClassTable(State& state)
- {
- assert(mClassTable);
-
- mClassTable.PushRef(state);
- }
-
- template<class TYPE, class BASE>
- void NativeClass<TYPE, BASE>::SetClassTableRef(State& state, int idx)
- {
- mClassTable.SetRef(state, idx);
- }
-
- template<class TYPE, class BASE>
- NativeClass<TYPE, BASE>::NativeClass()
- : mWatchDog()
-#if LUA_BIND_PROFILER
- , mSafer(false)
-#endif
- {
- }
-
- template<class TYPE, class BASE>
- NativeClass<TYPE, BASE>::~NativeClass()
- {
- }
-
-#if LUA_BIND_PROFILER
- template<class TYPE, class BASE>
- void NativeClass<TYPE, BASE>::operator delete(void* pdead, size_t size)
- {
- if (pdead == nullptr)
- return;
- // 堆上创建的实例必须使用Release释放。
- TYPE* p = static_cast<TYPE*>(pdead);
- assert(p->mSafer);
- ::operator delete(pdead, size);
- }
-#endif
-
- template<class TYPE, class BASE>
- void NativeClass<TYPE, BASE>::Retain()
- {
- ++mWatchDog.mNativeRef;
- }
-
- template<class TYPE, class BASE>
- void NativeClass<TYPE, BASE>::Release()
- {
- if (mWatchDog.mNativeRef > 0)
- --mWatchDog.mNativeRef;
- if (mWatchDog)
- {
-#if LUA_BIND_PROFILER
- mSafer = true;
-#endif
- delete this;
- }
- }
-
- template<class TYPE, class BASE>
- template<typename U>
- void NativeClass<TYPE, BASE>::Retain(State& state, U* userdata)
- {
- if (PushRefTable(state))
- {
- if (userdata->PushUserdata(state))
- {
- lua_pushvalue(state, -1); // copy the userdata
- lua_gettable(state, -3); // get the count (or nil)
- u32 count = state.GetValue<u32>(-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<class TYPE, class BASE>
- template<typename U>
- void NativeClass<TYPE, BASE>::Release(State& state, U* userdata)
- {
- if (PushRefTable(state))
- {
- if (userdata->PushUserdata(state))
- {
- lua_pushvalue(state, -1); // copy the userdata
- lua_gettable(state, -3); // get the count (or nil)
- u32 count = state.GetValue<u32>(-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<class TYPE, class BASE>
- bool NativeClass<TYPE, BASE>::PushUserdata(State& state)
- {
- assert(!TYPE::IsClassSingleton());
- if (!mUserdata)
- {
- BindToLua(state);
- return true;
- }
- return mUserdata.PushRef(state);
- }
-
- template<class TYPE, class BASE>
- bool NativeClass<TYPE, BASE>::PushMemberTable(State& state)
- {
- int top = state.GetTop();
- if (this->PushUserdata(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<class TYPE, class BASE>
- bool NativeClass<TYPE, BASE>::PushRefTable(State& state)
- {
- // Singleton
- if (TYPE::IsClassSingleton())
- {
- 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->PushUserdata(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<class TYPE, class BASE>
- void NativeClass<TYPE, BASE>::BindToLua(State& state)
- {
- // 单例不能绑定userdata
- assert(!TYPE::IsClassSingleton());
- assert(!mUserdata);
-
- // 创建userdata并留在栈顶,注意地址要转换为TYPE*,直接用this可能会导致多重继承的类丧失多态。
- // 如果直接传this进去,在多重继承情况下,是拿不到另一头的虚函数表的。所以这里需要将this
- // 转换为整个对象的低地址,这样可以拿到另一个基类的虚函数表,通过另一个基类实现多态。
- TYPE* p = static_cast<TYPE*>(this);
- state.PushPtrUserdata(p);
-
- lua_newtable(state); // ref table,无法在lua处访问,用来管理C对象的生命周期
- lua_newtable(state); // member table,lua中创建的对象成员都保存在这里
- PushClassTable(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 LUA_BIND_PROFILER
- mRefVMs.insert(state.GetVM());
-#endif
- }
-
- //
- // 成员引用管理
- //
- template<class TYPE, class BASE>
- void NativeClass<TYPE, BASE>::SetMemberRef(State& state, MemberRef& memRef, int idx)
- {
- ClearMemberRef(state, memRef);
- if (!lua_isnil(state, idx))
- {
- idx = state.AbsIndex(idx);
- if (PushRefTable(state))
- {
- lua_pushvalue(state, idx);
- memRef.refID = luaL_ref(state, -2);
- state.Pop(); // ref table
- }
- }
- }
-
- template<class TYPE, class BASE>
- bool NativeClass<TYPE, BASE>::PushMemberRef(State& state, MemberRef& memRef)
- {
- if (memRef)
- {
- if (PushRefTable(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<class TYPE, class BASE>
- bool NativeClass<TYPE, BASE>::PushMemberRef(State& state, int refID)
- {
- if (PushRefTable(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<class TYPE, class BASE>
- void NativeClass<TYPE, BASE>::ClearMemberRef(State& state, MemberRef& memRef)
- {
- if (memRef)
- {
- if (PushRefTable(state))
- {
- luaL_unref(state, -1, memRef.refID);
- state.Pop(); // ref table
- }
- memRef.refID = LUA_NOREF;
- }
- }
-
- //--------------------------------------------------------------------------------//
-
- //
- // 释放工厂创建的实例
- //
- template<class TYPE, class BASE>
- int NativeClass<TYPE, BASE>::__gc(lua_State* L)
- {
- LUA_BIND_STATE(L);
-
- TYPE* self = state.GetUserdata<TYPE>(1);
- assert(self);
-
-#if LUA_BIND_PROFILER
- std::cout << ": GC<" << TYPE::GetClassName() << ">\n";
-#endif
-
- if(self->mWatchDog.mVMRef > 0)
- --self->mWatchDog.mVMRef;
-
- self->Release();
-
- return 0;
- }
-
- //
- // 输出格式如下:
- // 地址 类名
- //
- template<class TYPE, class BASE>
- int NativeClass<TYPE, BASE>::__tostring(lua_State* L)
- {
- // params:
- // 1: userdata
-
- LUA_BIND_STATE(L);
- TYPE* self = state.GetUserdata<TYPE>(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<cc8*>(-1, "");
- }
- else
- {
- classname = TYPE::GetClassName();
- }
- lua_pushfstring(L, "%s: %p", classname, self);
- return 1;
- }
- return 0;
- }
-
-#if LUA_BIND_ENABLE_NATIVE_EXTEND
- // 派生出子类,在lua里对派生类的成员和行为进行重新设计,但是保证了userdata的统一。Native class的派生提供__init支持,在
- // native实体创建后可以使用__init进行初始化,派生类拥有和基类一样的New参数列表,且native对象是一样的类型。
- template<class TYPE, class BASE>
- int NativeClass<TYPE, BASE>::_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<class TYPE, class BASE>
- int NativeClass<TYPE, BASE>::_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;
- }
-
- template<class TYPE, class BASE>
- int NativeClass<TYPE, BASE>::_New(lua_State* L)
- {
- LUA_BIND_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;
- }
-
-#endif /*LUA_BIND_ENABLE_NATIVE_EXTEND*/
-
- template<class TYPE, class BASE>
- int NativeClass<TYPE, BASE>::_GetClass(lua_State* L)
- {
- LUA_BIND_STATE(L);
- if (!mClassTable)
- lua_pushnil(L);
- else
- mClassTable.PushRef(state);
- return 1;
- }
-
- template<class TYPE, class BASE>
- int NativeClass<TYPE, BASE>::_GetRefTable(lua_State* L)
- {
- LUA_BIND_STATE(L);
- TYPE* self = state.GetUserdata<TYPE>(1);
- bool success = self->PushRefTable(state);
- if (!success)
- lua_pushnil(L);
- return 1;
- }
-
- template<class TYPE, class BASE> StrongRef NativeClass<TYPE, BASE>::mClassTable; // class table
- template<class TYPE, class BASE> StrongRef NativeClass<TYPE, BASE>::mSingletonRefTable; // 单例
-
} \ No newline at end of file
diff --git a/Runtime/Lua/LuaBind/LuaBindRef.cpp b/Runtime/Lua/LuaBind/LuaBindRef.cpp
index 00a65d0..676525a 100644
--- a/Runtime/Lua/LuaBind/LuaBindRef.cpp
+++ b/Runtime/Lua/LuaBind/LuaBindRef.cpp
@@ -4,7 +4,7 @@
namespace LuaBind
{
- Ref::Ref(int mode)
+ Ref::Ref(RefMode mode)
: mRefID(LUA_NOREF)
, mMode(mode)
{
@@ -12,6 +12,8 @@ namespace LuaBind
Ref::~Ref()
{
+ // 自动释放引用
+
}
Ref::operator bool()
diff --git a/Runtime/Lua/LuaBind/LuaBindRef.h b/Runtime/Lua/LuaBind/LuaBindRef.h
index 93b30be..7058094 100644
--- a/Runtime/Lua/LuaBind/LuaBindRef.h
+++ b/Runtime/Lua/LuaBind/LuaBindRef.h
@@ -7,9 +7,7 @@
namespace LuaBind
{
- //
- // 引用,存在LUA_REGISTRYINDEX下面的两个表里
- //
+ // 全局引用,保存在LUA_REGISTRYINDEX下面的两个表里
class Ref
{
public:
@@ -20,26 +18,29 @@ namespace LuaBind
WEAK_REF
};
- Ref(int mode = STRONG_REF);
+ Ref(RefMode mode = STRONG_REF);
virtual ~Ref();
operator bool();
+ // 将栈上的对象添加到全局引用表中
void SetRef(State& state, int idx);
+
+ // 将引用的对象压入栈
bool PushRef(State& state);
- int GetRefID();
+ int GetRefID() { return mRefID; }
+
+ RefMode GetRefMode() { return mMode; }
private:
- int mRefID; // luaL_ref
- int mMode; // strong or weak
+ int mRefID;
+ RefMode mMode;
};
- //
- // 强引用,在LUA_REGISTRYINDEX["_LUA_BIND_STRONGREF_TABLE"]里,保证lua object不会被回收。
- //
+ // 强引用,在LUA_REGISTRYINDEX["GAMELAB_UNIVERSAL_STRONG_REFERENCE_TABLE"]里,保证lua object不会被回收
class StrongRef: public Ref
{
public:
@@ -47,9 +48,7 @@ namespace LuaBind
};
- //
- // 弱引用,在LUA_REGISTRYINDEX["_LUA_BIND_WEAKREF_TABLE"]里,不影响lua object的回收,只是作为一个方便取lua object的映射。
- //
+ // 弱引用,在LUA_REGISTRYINDEX["GAMELAB_UNIVERSAL_WEAK_REFERENCE_TABLE"]里,不影响lua object的回收,只是作为一个方便取lua object的映射
class WeakRef : public Ref
{
public:
diff --git a/Runtime/Lua/LuaBind/LuaBindRefTable.h b/Runtime/Lua/LuaBind/LuaBindRefTable.h
index 0d4c2d4..3401a53 100644
--- a/Runtime/Lua/LuaBind/LuaBindRefTable.h
+++ b/Runtime/Lua/LuaBind/LuaBindRefTable.h
@@ -8,9 +8,7 @@ namespace LuaBind
class State;
- //
// ref table 管理,对strong ref table和weak ref table两个table的代理。
- //
class RefTable
{
public:
@@ -31,25 +29,17 @@ namespace LuaBind
bool IsKeyWeak();
bool IsValueWeak();
- //
// 对stack[idx]的实体在此ref table中增加一个引用,并返回refID
- //
int Ref(State& state, int idx);
void Unref(State& state, int refID);
- //
// 将此 ref table 放在栈顶
- //
void PushRefTable(State& state);
- //
// 将 reftable[refID] 放在栈顶
- //
void PushRef(State& state, int refID);
- //
// 清空 ref table,表还留在LUA_REGISTRYINDEX[mName]
- //
void Clear(State& state);
private:
diff --git a/Runtime/Lua/LuaBind/LuaBindState.h b/Runtime/Lua/LuaBind/LuaBindState.h
index ec2a350..9028583 100644
--- a/Runtime/Lua/LuaBind/LuaBindState.h
+++ b/Runtime/Lua/LuaBind/LuaBindState.h
@@ -286,10 +286,13 @@ namespace LuaBind
TYPE::RegisterFactoryClass(state);
TYPE::RegisterClass(state);
- // 自定义流程
+ // 自定义注册内容
if (onRegisterFactoryClass)
onRegisterFactoryClass(state, clsIdx, type, g_NameSpace);
+ // 清理栈
+ lua_settop(state, clsIdx);
+
// 检测TYPE里面是否没有注册必须的方法
#define _assertmethod(I, NAME) \
GetField(I, NAME); \