diff options
Diffstat (limited to 'Runtime/Scripting/luax_class.hpp')
-rw-r--r-- | Runtime/Scripting/luax_class.hpp | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/Runtime/Scripting/luax_class.hpp b/Runtime/Scripting/luax_class.hpp new file mode 100644 index 0000000..12eb268 --- /dev/null +++ b/Runtime/Scripting/luax_class.hpp @@ -0,0 +1,207 @@ +#ifndef __LUAX_CLASS_H__ +#define __LUAX_CLASS_H__ + +#include "luax_config.h" + +#if LUAX_PROFILER +#include <unordered_set> +#endif + +#include <vector> + +#include "luax_ref.h" +#include "luax_memberref.h" +#include "luax_cfunctions.h" +#include "luax_watchdog.h" +#include "luax_utility.h" + +namespace Luax +{ + + class LuaxVM; + + /// + /// 虚基类,为了实现多态。需要访问下面这些接口的外部基类需要虚继承此类,之后再派生链中就会 + /// 调用对应实体的方法。注意继承此类时不能实现下面的方法,实现在LuaxNativeClass中,实现会 + /// 导致二义性。 + /// + /// 依据Effective C++条款40,如果在必须使用virtual base基类情况下,应该尽可能避免向其中放 + /// 置数据成员,规避数据成员初始化造成的一些隐性问题。依据这一点,vpb基类更加接近C#和Java中 + /// 的Interface。所以,在这里把类用I开头标识这是一个接口。 + /// + class LuaxObject + { + public: + LuaxObject() {}; + virtual ~LuaxObject() {}; + + /// + /// 成员引用管理,在实例的ref table里。设置、取、清除。 + /// + virtual bool PushLuaxMemberRef(LuaxState& state, int refID) = 0; + virtual bool PushLuaxUserdata(LuaxState& state) = 0; + virtual bool PushLuaxMemberTable(LuaxState& state) = 0; + virtual bool PushLuaxRefTable(LuaxState& state) = 0; + + /// + /// 被LuaxNativeClass实现。保持和释放native资源。 + /// + virtual void Retain() = 0; + virtual void Release() = 0; + + }; + + // TODO: 将公共部分提取出来,不要重复生成代码 + //class LuaxNativeClassBase + //{ + //} + + /// + /// 需要暴露给lua的native class需要继承此类。通过lua管理的实例要确保引用计数的正确性,在多个线程中需要确 + /// 定不会误释放。 + /// + template<class TYPE, class BASE = LuaxObject> + class LuaxNativeClass : public BASE + { + public: + + /// + /// 将userdata作为key,在ref table里对userdata添加一个引用,以维持userdata的生命周期。 + /// 相比较member ref,这个用在实体会被多次被不同其他实体引用的情况,并频繁销毁这些实体, + /// 避免lua频繁的调用gc检测。 + /// + template<class DATATYPE> void LuaxRetain(LuaxState& state, DATATYPE* userdata); + + /// + /// 对userdata减少一个引用在ref table里,以尝试回收userdata。 + /// + template<class DATATYPE> void LuaxRelease(LuaxState& state, DATATYPE* userdata); + + /// + /// 将userdata push到栈顶,如果没有初始化mUserdata,初始化设置好元表并把初始化好的 + /// userdata留在栈顶。并添加一个引用。这是一个将native对象所有权移交给lua控制的方法。 + /// + bool PushLuaxMemberRef(LuaxState& state, int refID) override; + bool PushLuaxUserdata(LuaxState& state) override; + bool PushLuaxMemberTable(LuaxState& state) override; + bool PushLuaxRefTable(LuaxState& state) override; + + /// + /// Watch dog 添加一个native引用。luaVM引用不会提供外部接口。继承此类的派生类不能直接使用 + /// delete方法,应该使用Release释放。一般情况下这个操作由虚拟机__gc进行,但是允许用户 + /// 程序在native中隔绝虚拟机情况下释放,这种情况下要使用Release。 + /// + /// 这两个函数是native接口。 + /// + void Retain() override final; + void Release() override final; + +#if LUAX_PROFILER + // 对堆上创建的实例进行delete保险检查 + static void operator delete(void* pdead, size_t size); +#endif + + protected: + + LuaxNativeClass(); + virtual ~LuaxNativeClass(); + + /// + /// 成员引用管理,在实例的ref table里。设置、取、清除 + /// + void SetLuaxMemberRef(LuaxState& state, LuaxMemberRef& memRef, int idx); + bool PushLuaxMemberRef(LuaxState& state, LuaxMemberRef& memRef); + void ClearLuaxMemberRef(LuaxState& state, LuaxMemberRef& memRef); + + private: + + friend class LuaxState; + + static void RegisterLuaxClassShared(LuaxState& state); + static void RegisterLuaxFactoryClass(LuaxState& state); + static void RegisterLuaxSingletonClass(LuaxState& state); + + static void SetLuaxClassTableRef(LuaxState& state, int idx); + static void PushLuaxClassTable(LuaxState& state); + + /// + /// 创建userdata,绑定实例到state。 + /// + void BindToLua(LuaxState& 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 LUAX_ENABLE_NATIVE_EXTEND + static int _ExtendFactory (lua_State*); + static int _ExtendSingleton (lua_State*); +#endif + + //--------------------------------------------------------------------------------// + + /// + /// class table,工厂和单例都有。 + /// + static LuaxStrongRef mClassTable; + + /// + /// 如果类是单例,这个用来保存singleton的引用关系,以保证不会被回收类似普通类的ref table。 + /// 单例的成员是全生命周期的,所以直接在_LUAX_STRONGREF_TABLE。单例对userdata进行 + /// LuaxRetain\LuaxRelease和member ref操作时和工厂实例不同,是存在下面这个ref table里 + /// 的,这个table在_LUAX_STRONGREF_TABLE里。 + /// + static LuaxStrongRef mSingletonRefTable; + + /// + /// 通过userdata可以拿到: + /// 1: ref table + /// 2: member table + /// 3: class table + /// + LuaxWeakRef mUserdata; + + /// 通过后才能删除 + LuaxWatchDog mWatchDog; + +#if LUAX_PROFILER + // 托管此对象的虚拟机 + std::unordered_set<LuaxVM*> mRefVMs; + // 保险,此类的派生类不能在外部使用delete直接删除,而应该使用Release + bool mSafer; +#endif + + }; + +#if LUAX_ENABLE_PLAIN_CLASS + /// + /// 纯lua类 + /// + class LuaxPlainClass + { + public: + + /// + /// 用来注册类的入口函数。可以通过registry(类名)注册类。 + /// + static int registry(lua_State* L); + + LUAX_DECL_METHOD(__tostring); + LUAX_DECL_METHOD(_Extend); + LUAX_DECL_METHOD(_New); + LUAX_DECL_METHOD(_TypeOf); + + }; +#endif + +} + +#endif
\ No newline at end of file |