summaryrefslogtreecommitdiff
path: root/Runtime/Scripting/LuaBindClass.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'Runtime/Scripting/LuaBindClass.hpp')
-rw-r--r--Runtime/Scripting/LuaBindClass.hpp207
1 files changed, 207 insertions, 0 deletions
diff --git a/Runtime/Scripting/LuaBindClass.hpp b/Runtime/Scripting/LuaBindClass.hpp
new file mode 100644
index 0000000..c7cfca5
--- /dev/null
+++ b/Runtime/Scripting/LuaBindClass.hpp
@@ -0,0 +1,207 @@
+#ifndef __LUA_BIND_CLASS_H__
+#define __LUA_BIND_CLASS_H__
+
+#include "LuaBindConfig.h"
+
+#if LUA_BIND_PROFILER
+#include <unordered_set>
+#endif
+
+#include <vector>
+
+#include "LuaBindRef.h"
+#include "LuaBindMemberRef.h"
+#include "LuaBindCFunctions.h"
+#include "LuaBindWatchDog.h"
+#include "LuaBindUtility.h"
+
+namespace LuaBind
+{
+
+ class LuaBindVM;
+
+ ///
+ /// 虚基类,为了实现多态。需要访问下面这些接口的外部基类需要虚继承此类,之后再派生链中就会
+ /// 调用对应实体的方法。注意继承此类时不能实现下面的方法,实现在LuaBindNativeClass中,实现会
+ /// 导致二义性。
+ ///
+ /// 依据Effective C++条款40,如果在必须使用virtual base基类情况下,应该尽可能避免向其中放
+ /// 置数据成员,规避数据成员初始化造成的一些隐性问题。依据这一点,vpb基类更加接近C#和Java中
+ /// 的Interface。所以,在这里把类用I开头标识这是一个接口。
+ ///
+ class LuaBindObject
+ {
+ public:
+ LuaBindObject() {};
+ virtual ~LuaBindObject() {};
+
+ ///
+ /// 成员引用管理,在实例的ref table里。设置、取、清除。
+ ///
+ virtual bool PushLuaBindMemberRef(LuaBindState& state, int refID) = 0;
+ virtual bool PushLuaBindUserdata(LuaBindState& state) = 0;
+ virtual bool PushLuaBindMemberTable(LuaBindState& state) = 0;
+ virtual bool PushLuaBindRefTable(LuaBindState& state) = 0;
+
+ ///
+ /// 被LuaBindNativeClass实现。保持和释放native资源。
+ ///
+ virtual void Retain() = 0;
+ virtual void Release() = 0;
+
+ };
+
+ // TODO: 将公共部分提取出来,不要重复生成代码
+ //class LuaBindNativeClassBase
+ //{
+ //}
+
+ ///
+ /// 需要暴露给lua的native class需要继承此类。通过lua管理的实例要确保引用计数的正确性,在多个线程中需要确
+ /// 定不会误释放。
+ ///
+ template<class TYPE, class BASE = LuaBindObject>
+ class LuaBindNativeClass : public BASE
+ {
+ public:
+
+ ///
+ /// 将userdata作为key,在ref table里对userdata添加一个引用,以维持userdata的生命周期。
+ /// 相比较member ref,这个用在实体会被多次被不同其他实体引用的情况,并频繁销毁这些实体,
+ /// 避免lua频繁的调用gc检测。
+ ///
+ template<class DATATYPE> void LuaBindRetain(LuaBindState& state, DATATYPE* userdata);
+
+ ///
+ /// 对userdata减少一个引用在ref table里,以尝试回收userdata。
+ ///
+ template<class DATATYPE> void LuaBindRelease(LuaBindState& state, DATATYPE* userdata);
+
+ ///
+ /// 将userdata push到栈顶,如果没有初始化mUserdata,初始化设置好元表并把初始化好的
+ /// userdata留在栈顶。并添加一个引用。这是一个将native对象所有权移交给lua控制的方法。
+ ///
+ bool PushLuaBindMemberRef(LuaBindState& state, int refID) override;
+ bool PushLuaBindUserdata(LuaBindState& state) override;
+ bool PushLuaBindMemberTable(LuaBindState& state) override;
+ bool PushLuaBindRefTable(LuaBindState& state) override;
+
+ ///
+ /// Watch dog 添加一个native引用。luaVM引用不会提供外部接口。继承此类的派生类不能直接使用
+ /// delete方法,应该使用Release释放。一般情况下这个操作由虚拟机__gc进行,但是允许用户
+ /// 程序在native中隔绝虚拟机情况下释放,这种情况下要使用Release。
+ ///
+ /// 这两个函数是native接口。
+ ///
+ void Retain() override final;
+ void Release() override final;
+
+#if LUA_BIND_PROFILER
+ // 对堆上创建的实例进行delete保险检查
+ static void operator delete(void* pdead, size_t size);
+#endif
+
+ protected:
+
+ LuaBindNativeClass();
+ virtual ~LuaBindNativeClass();
+
+ ///
+ /// 成员引用管理,在实例的ref table里。设置、取、清除
+ ///
+ void SetLuaBindMemberRef(LuaBindState& state, LuaBindMemberRef& memRef, int idx);
+ bool PushLuaBindMemberRef(LuaBindState& state, LuaBindMemberRef& memRef);
+ void ClearLuaBindMemberRef(LuaBindState& state, LuaBindMemberRef& memRef);
+
+ private:
+
+ friend class LuaBindState;
+
+ static void RegisterLuaBindClassShared(LuaBindState& state);
+ static void RegisterLuaBindFactoryClass(LuaBindState& state);
+ static void RegisterLuaBindSingletonClass(LuaBindState& state);
+
+ static void SetLuaBindClassTableRef(LuaBindState& state, int idx);
+ static void PushLuaBindClassTable(LuaBindState& state);
+
+ ///
+ /// 创建userdata,绑定实例到state。
+ ///
+ void BindToLua(LuaBindState& state);
+
+ //------------------------------------------------------------------------------//
+
+ // 公共内容
+ static int __tostring (lua_State*);
+ static int _GetClass (lua_State*);
+ static int _GetClassName (lua_State*);
+
+ // 工厂类相关
+ static int __gc (lua_State*);
+ static int _GetRefTable (lua_State*);
+ static int _New (lua_State*);
+
+#if LUA_BIND_ENABLE_NATIVE_EXTEND
+ static int _ExtendFactory (lua_State*);
+ static int _ExtendSingleton (lua_State*);
+#endif
+
+ //--------------------------------------------------------------------------------//
+
+ ///
+ /// class table,工厂和单例都有。
+ ///
+ static LuaBindStrongRef mClassTable;
+
+ ///
+ /// 如果类是单例,这个用来保存singleton的引用关系,以保证不会被回收类似普通类的ref table。
+ /// 单例的成员是全生命周期的,所以直接在_LUA_BIND_STRONGREF_TABLE。单例对userdata进行
+ /// LuaBindRetain\LuaBindRelease和member ref操作时和工厂实例不同,是存在下面这个ref table里
+ /// 的,这个table在_LUA_BIND_STRONGREF_TABLE里。
+ ///
+ static LuaBindStrongRef mSingletonRefTable;
+
+ ///
+ /// 通过userdata可以拿到:
+ /// 1: ref table
+ /// 2: member table
+ /// 3: class table
+ ///
+ LuaBindWeakRef mUserdata;
+
+ /// 通过后才能删除
+ LuaBindWatchDog mWatchDog;
+
+#if LUA_BIND_PROFILER
+ // 托管此对象的虚拟机
+ std::unordered_set<LuaBindVM*> mRefVMs;
+ // 保险,此类的派生类不能在外部使用delete直接删除,而应该使用Release
+ bool mSafer;
+#endif
+
+ };
+
+#if LUA_BIND_ENABLE_PLAIN_CLASS
+ ///
+ /// 纯lua类
+ ///
+ class LuaBindPlainClass
+ {
+ public:
+
+ ///
+ /// 用来注册类的入口函数。可以通过registry(类名)注册类。
+ ///
+ static int registry(lua_State* L);
+
+ LUA_BIND_DECL_METHOD(__tostring);
+ LUA_BIND_DECL_METHOD(_Extend);
+ LUA_BIND_DECL_METHOD(_New);
+ LUA_BIND_DECL_METHOD(_TypeOf);
+
+ };
+#endif
+
+}
+
+#endif \ No newline at end of file