From d29f5f4aebd90b1e256967801b28a5990249b2e7 Mon Sep 17 00:00:00 2001 From: chai Date: Sat, 16 Mar 2019 19:29:23 +0800 Subject: *luax --- Source/3rdParty/Luax/luax.h | 2 +- Source/3rdParty/Luax/luax_cfunctions.cpp | 19 ++++ Source/3rdParty/Luax/luax_cfunctions.h | 25 +++++ Source/3rdParty/Luax/luax_class.hpp | 44 +++++--- Source/3rdParty/Luax/luax_class.inl | 182 +++++++++++++++++++++++++++---- Source/3rdParty/Luax/luax_function.cpp | 0 Source/3rdParty/Luax/luax_function.h | 11 -- Source/3rdParty/Luax/luax_memberref.cpp | 16 +++ Source/3rdParty/Luax/luax_memberref.h | 11 +- Source/3rdParty/Luax/luax_state.cpp | 4 +- Source/3rdParty/Luax/luax_state.h | 2 +- Source/3rdParty/Luax/luax_state.inl | 8 +- 12 files changed, 267 insertions(+), 57 deletions(-) create mode 100644 Source/3rdParty/Luax/luax_cfunctions.cpp create mode 100644 Source/3rdParty/Luax/luax_cfunctions.h delete mode 100644 Source/3rdParty/Luax/luax_function.cpp delete mode 100644 Source/3rdParty/Luax/luax_function.h (limited to 'Source/3rdParty') diff --git a/Source/3rdParty/Luax/luax.h b/Source/3rdParty/Luax/luax.h index 9a6b0b9..6935e71 100644 --- a/Source/3rdParty/Luax/luax.h +++ b/Source/3rdParty/Luax/luax.h @@ -6,9 +6,9 @@ #include "luax_namespace.h" #include "luax_ref.h" #include "luax_reftable.h" -#include "luax_memberref.h" #include "luax_enum.h" #include "luax_class.hpp" +#include "luax_memberref.h" #include "luax_class.inl" #include "luax_state.inl" diff --git a/Source/3rdParty/Luax/luax_cfunctions.cpp b/Source/3rdParty/Luax/luax_cfunctions.cpp new file mode 100644 index 0000000..d93a0ee --- /dev/null +++ b/Source/3rdParty/Luax/luax_cfunctions.cpp @@ -0,0 +1,19 @@ +#include "luax_cfunctions.h" +#include "luax_config.h" + +namespace Luax +{ + + int luax_c_getupvalue(lua_State* L) + { + lua_pushvalue(L, lua_upvalueindex(1)); + return 1; + } + + int luax_c_errfunc(lua_State* L) + { + cc8* msg = luaL_optstring(L, lua_upvalueindex(1), ""); + return luaL_error(L, msg); + } + +} \ No newline at end of file diff --git a/Source/3rdParty/Luax/luax_cfunctions.h b/Source/3rdParty/Luax/luax_cfunctions.h new file mode 100644 index 0000000..2570bb9 --- /dev/null +++ b/Source/3rdParty/Luax/luax_cfunctions.h @@ -0,0 +1,25 @@ +#ifndef __LUAX_CFUNCTIONS_H__ +#define __LUAX_CFUNCTIONS_H__ + +#include "luax_config.h" + +/** + * luax_cfunction里的函数用来注册给lua,一些特殊功能的通用函数。 +*/ + +namespace Luax +{ + + /// + /// 获得第一个upvalue + /// + extern int luax_c_getupvalue(lua_State* L); + + /// + /// 调用此函数时会报错,upvalue(1)是错误信息 + /// + extern int luax_c_errfunc(lua_State* L); + +} + +#endif \ No newline at end of file diff --git a/Source/3rdParty/Luax/luax_class.hpp b/Source/3rdParty/Luax/luax_class.hpp index a76d501..539093c 100644 --- a/Source/3rdParty/Luax/luax_class.hpp +++ b/Source/3rdParty/Luax/luax_class.hpp @@ -5,6 +5,7 @@ #include "luax_config.h" #include "luax_ref.h" +#include "luax_memberref.h" namespace Luax { @@ -30,6 +31,7 @@ namespace Luax /// #define LUAX_DECL_SINGLETON(type) \ static void RegisterLuaxClass(Luax::LuaxState&); \ + static void RegisterLuaxPostprocess(Luax::LuaxState&); \ static const char* GetLuaxSingletonName() { return #type; }; \ static const char* GetLuaxClassName() { return #type; }; \ static bool IsLuaxClassSingleton() { return true; }; @@ -42,8 +44,15 @@ namespace Luax { public: - void Retain(); - void Release(); + /// + /// 将userdata作为key,在ref table里对userdata添加一个引用,以维持userdata的生命周期。 + /// + template void LuaRetain(LuaxState& state, U* userdata); + + /// + /// 对userdata减少一个引用在ref table里,以尝试回收userdata。 + /// + template void LuaRelease(LuaxState& state, U* userdata); protected: @@ -57,6 +66,13 @@ namespace Luax bool PushLuaxMemberTable(LuaxState& state); bool PushLuaxRefTable(LuaxState& state); + /// + /// 成员引用管理,在实例的ref table里。设置、取、清除 + /// + void SetMemberRef(LuaxState& state, LuaxMemberRef& memRef, int idx); + bool PushMemberRef(LuaxState& state, LuaxMemberRef& memRef); + void ClearMemberRef(LuaxState& state, LuaxMemberRef& memRef); + private: friend class LuaxState; @@ -80,7 +96,7 @@ namespace Luax void* operator &(); /// - /// 创建userdata,绑定实例到state,如果本类是工厂 + /// 创建userdata,绑定实例到state。 /// void BindToLua(LuaxState& state); @@ -102,30 +118,22 @@ namespace Luax /// LuaxWeakRef mUserdata; - /// - /// 引用计数,用来处理线程间共享 - /// - int mRC; - - /// - /// 确保析构函数只能通过Release调用的safer,这样只要继承了LuaxClass的类,如果使用delete直接析构,就会报错 - /// - bool mSafer; - public: //------------------------------------------------------------------------------------------------------------ // 公共内容 - LUAX_DECL_METHOD( l_GetClassName ); - LUAX_DECL_METHOD( l_GetInterfaceTable ); - LUAX_DECL_METHOD( l___tostring ); + LUAX_DECL_METHOD( l___tostring ); + LUAX_DECL_METHOD( l_GetClassName ); //------------------------------------------------------------------------------------------------------------ // 工厂类相关 - LUAX_DECL_METHOD( l_ExtendFactory ); - LUAX_DECL_METHOD( l___gc ); + LUAX_DECL_METHOD( l___gc ); + LUAX_DECL_METHOD( l_ExtendFactory ); + LUAX_DECL_METHOD( l_GetClass ); + LUAX_DECL_METHOD( l_GetInterfaceTable ); + LUAX_DECL_METHOD( l_GetRefTable ); //------------------------------------------------------------------------------------------------------------ // 单例类相关 diff --git a/Source/3rdParty/Luax/luax_class.inl b/Source/3rdParty/Luax/luax_class.inl index 8cf0f55..bbda6de 100644 --- a/Source/3rdParty/Luax/luax_class.inl +++ b/Source/3rdParty/Luax/luax_class.inl @@ -5,7 +5,7 @@ namespace Luax // 接口 /// - /// 对不同类型,通过调用GetLuaClassName获得类型名 + /// 对不同类型,通过调用GetLuaClassName获得类型名,如果是派生类,GetClassName会被覆盖,指向luax_c_getupvalue。 /// template int LuaxClass::l_GetClassName(lua_State* L) @@ -33,7 +33,6 @@ namespace Luax state.RegisterMethods(regTable); } - /// /// 工厂类的成员,注册在class table /// @@ -48,7 +47,6 @@ namespace Luax state.RegisterMethods(regTable); } - /// /// 工厂实例的成员,注册在interface table /// @@ -56,14 +54,14 @@ namespace Luax void LuaxClass::RegisterLuaxInterface(LuaxState& state) { luaL_Reg regTable[] = { - { "__gc", l___gc }, - { NULL, NULL } + { "GetClass", l_GetClass }, + { "GetRefTable", l_GetRefTable }, + { NULL, NULL } }; state.RegisterMethods(regTable); } - /// /// 单例类的成员,注册在class table /// @@ -107,30 +105,55 @@ namespace Luax template LuaxClass::LuaxClass() - : mRC(1) // 构造时默认有一个引用 - , mSafer(false) { } template LuaxClass::~LuaxClass() { - assert(mSafer); } template - void LuaxClass::Retain() + template + void LuaxClass::LuaRetain(LuaxState& state, U* userdata) { - ++mRC; + 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 - void LuaxClass::Release() + template + void LuaxClass::LuaRelease(LuaxState& state, U* userdata) { - if (--mRC <= 0) + if (PushLuaxRefTable(state)) { - mSafer = true; // 打开析构safer - delete this; + 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 + } } } @@ -197,6 +220,12 @@ namespace Luax return false; } + /// + /// 创建userdata,并以此添加ref table,member table和interface table。 + /// ref table 是kv强引用table,保存对其他userdata的引用计数(通过userdata作为key,计数为value),以及成员引用 + /// member table 保存lua创建的实例的成员 + /// interface table 所有本类型的实例共有的成员函数表 + /// template void LuaxClass::BindToLua(LuaxState& state) { @@ -221,14 +250,14 @@ namespace Luax int memberTable = top - 1; int refTable = top - 2; - // ref table 注册 __gc和__tostring + // ref table 注册 __gc 和 __tostring lua_pushcfunction(state, l___gc); lua_setfield(state, refTable, "__gc"); lua_pushcfunction(state, l___tostring); lua_setfield(state, refTable, "__tostring"); - // member table 设为 ref table 的 __index 和 __newindex + // ref table 的 __index 和 __newindex 设为 member table lua_pushvalue(state, memberTable); lua_setfield(state, refTable, "__index"); @@ -245,6 +274,59 @@ namespace Luax assert(mUserdata); } + /// + /// 成员引用管理 + /// + template + void LuaxClass::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 LuaxClass::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 LuaxClass::ClearMemberRef(LuaxState& state, LuaxMemberRef& memRef) + { + if (memRef) + { + if (PushLuaxRefTable(state)) + { + luaL_unref(state, -1, memRef.refID); + state.Pop(); // ref table + } + memRef.refID = LUA_NOREF; + } + } + //-------------------------------------------------------------------------------------------------------------- /// @@ -258,15 +340,51 @@ namespace Luax return 0; } + /// + /// 输出格式如下: + /// 地址 类名 + /// template int LuaxClass::l___tostring(lua_State* L) { + LUAX_STATE(L); + T* self = state.GetLuaUserdata(1); + if (self) + { + char buf[1024] = {0}; + const char* fmt = "%p <%s>"; + 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(); + } + sprintf(buf, fmt, self, classname); + lua_pushstring(L, buf); + return 1; + } return 0; } template int LuaxClass::l_ExtendFactory(lua_State* L) { + + + return 0; + } + + template + int LuaxClass::l_ExtendSingleton(lua_State* L) + { + + return 0; } @@ -274,9 +392,33 @@ namespace Luax int LuaxClass::l_GetInterfaceTable(lua_State* L) { LUAX_STATE(L); - assert(mInterfaceTable); - mInterfaceTable.PushRef(state); - return 0; + if (!mInterfaceTable) + lua_pushnil(L); + else + mInterfaceTable.PushRef(state); + return 1; + } + + template + int LuaxClass::l_GetClass(lua_State* L) + { + LUAX_STATE(L); + if (!mClassTable) + lua_pushnil(L); + else + mClassTable.PushRef(state); + return 1; + } + + template + int LuaxClass::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 LuaxStrongRef LuaxClass::mInterfaceTable; // interface table diff --git a/Source/3rdParty/Luax/luax_function.cpp b/Source/3rdParty/Luax/luax_function.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/Source/3rdParty/Luax/luax_function.h b/Source/3rdParty/Luax/luax_function.h deleted file mode 100644 index f4cc98b..0000000 --- a/Source/3rdParty/Luax/luax_function.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __LUAX_FUNCTION_H__ -#define __LUAX_FUNCTION_H__ - -namespace Luax -{ - - - -} - -#endif \ No newline at end of file diff --git a/Source/3rdParty/Luax/luax_memberref.cpp b/Source/3rdParty/Luax/luax_memberref.cpp index e69de29..a8a09ba 100644 --- a/Source/3rdParty/Luax/luax_memberref.cpp +++ b/Source/3rdParty/Luax/luax_memberref.cpp @@ -0,0 +1,16 @@ +#include "luax_memberref.h" + +namespace Luax +{ + + LuaxMemberRef::LuaxMemberRef() + : refID(LUA_NOREF) + { + } + + LuaxMemberRef::~LuaxMemberRef() + { + + } + +} \ No newline at end of file diff --git a/Source/3rdParty/Luax/luax_memberref.h b/Source/3rdParty/Luax/luax_memberref.h index a7ff1f6..bb373ab 100644 --- a/Source/3rdParty/Luax/luax_memberref.h +++ b/Source/3rdParty/Luax/luax_memberref.h @@ -1,14 +1,23 @@ #ifndef __LUAX_MEMBER_REF_H__ #define __LUAX_MEMBER_REF_H__ +#include "luax_config.h" + namespace Luax { /// - /// LuaxClass的成员引用,存在ref table里,保证正确释放,是强引用。 + /// 实例的ref table保存的member ref。由luax class做具体的管理。实例的ref table是强引用,用来管理里面member的生命周期。 /// class LuaxMemberRef { + public: + LuaxMemberRef(); + ~LuaxMemberRef(); + + inline operator bool() { return refID != LUA_NOREF; }; + + int refID; }; diff --git a/Source/3rdParty/Luax/luax_state.cpp b/Source/3rdParty/Luax/luax_state.cpp index 1414591..a60a021 100644 --- a/Source/3rdParty/Luax/luax_state.cpp +++ b/Source/3rdParty/Luax/luax_state.cpp @@ -100,9 +100,9 @@ namespace Luax return idx; } - int LuaxState::Call(int nArgs, int nResults) + void LuaxState::Call(int nArgs, int nResults) { - return 0; + lua_pcall(mState, nArgs, nResults, 0); } void LuaxState::PushNil() diff --git a/Source/3rdParty/Luax/luax_state.h b/Source/3rdParty/Luax/luax_state.h index a936ea6..2bcfd9b 100644 --- a/Source/3rdParty/Luax/luax_state.h +++ b/Source/3rdParty/Luax/luax_state.h @@ -54,7 +54,7 @@ namespace Luax int GetTop(); bool CheckParams(int idx, cc8* format); int AbsIndex(int idx); - int Call(int nArgs, int nResults); + void Call(int nArgs, int nResults); //------------------------------------------------------------------------------------------------------------ diff --git a/Source/3rdParty/Luax/luax_state.inl b/Source/3rdParty/Luax/luax_state.inl index bd7ca9a..c9a95f6 100644 --- a/Source/3rdParty/Luax/luax_state.inl +++ b/Source/3rdParty/Luax/luax_state.inl @@ -56,7 +56,7 @@ namespace Luax LuaxClass::SetLuaxClassTableRef(state, -1); - const char* type = T::GetLuaxFactoryName(); + cc8* type = T::GetLuaxFactoryName(); SetField(top, type); // reset top @@ -78,8 +78,6 @@ namespace Luax int top = lua_gettop(L); // namespace table assert(lua_istable(L, top)); - const char* type = T::GetLuaxSingletonName(); - // class table. lua_newtable(L); LuaxClass::RegisterLuaxClass(state); @@ -94,10 +92,14 @@ namespace Luax lua_pushvalue(state, -1); lua_setfield(state, -2, "__newindex"); + cc8* type = T::GetLuaxSingletonName(); SetField(top, type); // reset top lua_settop(L, top); + + // 后处理 + T::RegisterLuaxPostprocess(state); } template -- cgit v1.1-26-g67d0