summaryrefslogtreecommitdiff
path: root/Runtime/Lua/LuaBind/LuaBindClass.hpp
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-10-22 23:59:54 +0800
committerchai <chaifix@163.com>2021-10-22 23:59:54 +0800
commit4dafefe46a72ba47468b13d011f8299055081b0f (patch)
tree2a85835ec4d74fecf3815397b384cefe39d31f56 /Runtime/Lua/LuaBind/LuaBindClass.hpp
parent1f18d2afec632aa9361079ca3bcb5a7f2d73db3a (diff)
*LuaBind
Diffstat (limited to 'Runtime/Lua/LuaBind/LuaBindClass.hpp')
-rw-r--r--Runtime/Lua/LuaBind/LuaBindClass.hpp150
1 files changed, 40 insertions, 110 deletions
diff --git a/Runtime/Lua/LuaBind/LuaBindClass.hpp b/Runtime/Lua/LuaBind/LuaBindClass.hpp
index 154a4ce..f0fdf43 100644
--- a/Runtime/Lua/LuaBind/LuaBindClass.hpp
+++ b/Runtime/Lua/LuaBind/LuaBindClass.hpp
@@ -2,25 +2,24 @@
#define __LUA_BIND_CLASS_H__
#include "LuaBindConfig.h"
-
-#if LUA_BIND_PROFILER
#include <unordered_set>
-#endif
-
+#include <unordered_map>
#include <vector>
-
#include "LuaBindRef.h"
#include "LuaBindMemberRef.h"
#include "LuaBindCFunctions.h"
#include "LuaBindWatchDog.h"
#include "LuaBindUtility.h"
+#include "LuaBindHelper.h"
namespace LuaBind
{
-
class VM;
- //
+#define CLASS_NONE_ID (-1)
+
+ extern UIDGenerator gClassIDGenerator;
+
// 虚基类,为了实现多态。需要访问下面这些接口的外部基类需要虚继承此类,之后再派生链中就会
// 调用对应实体的方法。注意继承此类时不能实现下面的方法,实现在NativeClass中,实现会
// 导致二义性。
@@ -28,24 +27,19 @@ namespace LuaBind
// 依据Effective C++条款40,如果在必须使用virtual base基类情况下,应该尽可能避免向其中放
// 置数据成员,规避数据成员初始化造成的一些隐性问题。依据这一点,vpb基类更加接近C#和Java中
// 的Interface。所以,在这里把类用I开头标识这是一个接口。
- //
class Object
{
public:
Object() {};
virtual ~Object() {};
- //
// 成员引用管理,在实例的ref table里。设置、取、清除。
- //
virtual bool PushMemberRef(State& state, int refID) = 0;
virtual bool PushUserdata(State& state) = 0;
virtual bool PushMemberTable(State& state) = 0;
virtual bool PushRefTable(State& state) = 0;
- //
// 被NativeClass实现。保持和释放native资源。
- //
virtual void Retain() = 0;
virtual void Release() = 0;
@@ -56,43 +50,34 @@ namespace LuaBind
//{
//}
- //
// 需要暴露给lua的native class需要继承此类。通过lua管理的实例要确保引用计数的正确性,在多个线程中需要确
// 定不会误释放。
- //
template<class TYPE, class BASE = Object>
class NativeClass : public BASE
{
public:
+ enum NativeClassTableIndex { kRefTable = 1, kMemberTable = 2, kClassTable = 3 };
- //
// 将userdata作为key,在ref table里对userdata添加一个引用,以维持userdata的生命周期。
// 相比较member ref,这个用在实体会被多次被不同其他实体引用的情况,并频繁销毁这些实体,
// 避免lua频繁的调用gc检测。
- //
template<class DATATYPE> void Retain(State& state, DATATYPE* userdata);
- //
// 对userdata减少一个引用在ref table里,以尝试回收userdata。
- //
template<class DATATYPE> void Release(State& state, DATATYPE* userdata);
- //
// 将userdata push到栈顶,如果没有初始化mUserdata,初始化设置好元表并把初始化好的
// userdata留在栈顶。并添加一个引用。这是一个将native对象所有权移交给lua控制的方法。
- //
+ bool PushUserdata(State& state) override;
bool PushMemberRef(State& state, int refID) override;
- bool PushUserdata(State& state) override;
bool PushMemberTable(State& state) override;
bool PushRefTable(State& state) override;
- //
// WatchDog添加一个native引用。luaVM引用不会提供外部接口。继承此类的派生类不能直接使用
// delete方法,应该使用Release释放。一般情况下这个操作由虚拟机__gc进行,但是允许用户
// 程序在native中隔绝虚拟机情况下释放,这种情况下要使用Release。
//
// 这两个函数是native接口。
- //
void Retain() override final;
void Release() override final;
@@ -103,12 +88,11 @@ namespace LuaBind
protected:
- NativeClass();
+ // 需要指明对象所属的虚拟机
+ NativeClass(LuaBind::VM* vm);
virtual ~NativeClass();
- //
// 成员引用管理,在实例的ref table里。设置、取、清除
- //
void SetMemberRef(State& state, MemberRef& memRef, int idx);
bool PushMemberRef(State& state, MemberRef& memRef);
void ClearMemberRef(State& state, MemberRef& memRef);
@@ -119,14 +103,11 @@ namespace LuaBind
static void RegisterClassShared(State& state);
static void RegisterFactoryClass(State& state);
- static void RegisterSingletonClass(State& state);
static void SetClassTableRef(State& state, int idx);
static void PushClassTable(State& state);
- //
// 创建userdata,绑定实例到state。
- //
void BindToLua(State& state);
//------------------------------------------------------------------------------//
@@ -149,25 +130,16 @@ namespace LuaBind
//--------------------------------------------------------------------------------//
- //
- // class table,工厂和单例都有。
- //
- static StrongRef mClassTable;
+ // 类型的全局UID,在不同的虚拟机中相同
+ static int sClassID;
- //
- // 如果类是单例,这个用来保存singleton的引用关系,以保证不会被回收类似普通类的ref table。
- // 单例的成员是全生命周期的,所以直接在_LUA_BIND_STRONGREF_TABLE。单例对userdata进行
- // Retain\Release和member ref操作时和工厂实例不同,是存在下面这个ref table里
- // 的,这个table在_LUA_BIND_STRONGREF_TABLE里。
- //
- static StrongRef mSingletonRefTable;
+ // 所属的虚拟机
+ LuaBind::VM* mOwner;
- //
// 通过userdata可以拿到:
// 1: ref table
// 2: member table
// 3: class table
- //
WeakRef mUserdata;
// 通过后才能删除
@@ -204,10 +176,10 @@ namespace LuaBind
#endif
//--------------------------------------------------------------------------------//
+ template<class TYPE, class BASE>
+ int NativeClass<TYPE, BASE>::sClassID = CLASS_NONE_ID;
- //
// 对不同类型,通过调用GetLuaClassName获得类型名,如果是派生类,GetClassName会被覆盖,指向luax_c_getupvalue。
- //
template<class TYPE, class BASE>
int NativeClass<TYPE, BASE>::_GetClassName(lua_State* L)
{
@@ -220,9 +192,7 @@ namespace LuaBind
//--------------------------------------------------------------------------------//
- //
// 注册工厂和单例共有的类成员
- //
template<class TYPE, class BASE>
void NativeClass<TYPE, BASE>::RegisterClassShared(State& state)
{
@@ -235,9 +205,7 @@ namespace LuaBind
state.RegisterMethods(regTable);
}
- //
// 工厂类的成员,注册在class table
- //
template<class TYPE, class BASE>
void NativeClass<TYPE, BASE>::RegisterFactoryClass(State& state)
{
@@ -249,36 +217,27 @@ namespace LuaBind
state.RegisterMethods(regTable);
}
- //
- // 单例类的成员,注册在class table
- //
template<class TYPE, class BASE>
- void NativeClass<TYPE, BASE>::RegisterSingletonClass(State& state)
+ void NativeClass<TYPE, BASE>::SetClassTableRef(State& state, int idx)
{
- luaL_Reg regTable[] = {
- { NULL, NULL }
- };
-
- state.RegisterMethods(regTable);
+ if (sClassID == CLASS_NONE_ID)
+ sClassID = gClassIDGenerator.GetID();
+ LuaBind::VM* vm = state.GetVM();
+ vm->RegisterClassI(state, sClassID, idx);
}
template<class TYPE, class BASE>
void NativeClass<TYPE, BASE>::PushClassTable(State& state)
{
- assert(mClassTable);
-
- mClassTable.PushRef(state);
+ LuaBind::VM* vm = state.GetVM();
+ vm->PushClassTable(state, sClassID);
}
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()
+ NativeClass<TYPE, BASE>::NativeClass(LuaBind::VM* vm)
: mWatchDog()
+ , mUserdata(vm)
+ , mOwner(vm)
#if LUA_BIND_PROFILER
, mSafer(false)
#endif
@@ -380,8 +339,7 @@ namespace LuaBind
template<class TYPE, class BASE>
bool NativeClass<TYPE, BASE>::PushUserdata(State& state)
{
- assert(!TYPE::IsClassSingleton());
- if (!mUserdata)
+ if (!mUserdata) // 第一次创建
{
BindToLua(state);
return true;
@@ -413,28 +371,12 @@ namespace LuaBind
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 (this->PushUserdata(state))
+ if (lua_getmetatable(state, -1)) // RefTable
{
- if (lua_getmetatable(state, -1))
- {
- lua_replace(state, -2);
- return true;
- }
+ lua_replace(state, -2);
+ return true;
}
}
return false;
@@ -450,8 +392,6 @@ namespace LuaBind
template<class TYPE, class BASE>
void NativeClass<TYPE, BASE>::BindToLua(State& state)
{
- // 单例不能绑定userdata
- assert(!TYPE::IsClassSingleton());
assert(!mUserdata);
// 创建userdata并留在栈顶,注意地址要转换为TYPE*,直接用this可能会导致多重继承的类丧失多态。
@@ -465,10 +405,10 @@ namespace LuaBind
PushClassTable(state); // class table
// stack:
- // -1: class table
- // -2: member table
- // -3: ref table
- // -4: userdata
+ // -1 class table
+ // -2 member table
+ // -3 ref table
+ // -4 userdata
int top = state.GetTop();
int memberTable = top - 1;
@@ -488,10 +428,10 @@ namespace LuaBind
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 -> refTable -> memberTable -> classTable
+ lua_setmetatable(state, -2); // class is metatable of member
+ lua_setmetatable(state, -2); // member is metatable of ref
+ lua_setmetatable(state, -2); // ref is metatable of userdata
// 设置一个userdata的弱引用,方便通过PushLuaUserdata方法返回lua对象
mUserdata.SetRef(state, -1);
@@ -504,9 +444,7 @@ namespace LuaBind
#endif
}
- //
// 成员引用管理
- //
template<class TYPE, class BASE>
void NativeClass<TYPE, BASE>::SetMemberRef(State& state, MemberRef& memRef, int idx)
{
@@ -810,10 +748,7 @@ namespace LuaBind
int NativeClass<TYPE, BASE>::_GetClass(lua_State* L)
{
LUA_BIND_STATE(L);
- if (!mClassTable)
- lua_pushnil(L);
- else
- mClassTable.PushRef(state);
+ state.GetVM()->PushClassTable(state, sClassID);
return 1;
}
@@ -828,11 +763,6 @@ namespace LuaBind
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