From 34fe8e795aaeed3a9f50d895d1cadd8f124c9605 Mon Sep 17 00:00:00 2001 From: chai Date: Sun, 17 Mar 2019 20:36:39 +0800 Subject: *luax --- Source/3rdParty/Luax/luax_class.cpp | 33 +++++- Source/3rdParty/Luax/luax_class.hpp | 15 ++- Source/3rdParty/Luax/luax_class.inl | 184 +++++++++++++++++++++++++++-- Source/3rdParty/Luax/luax_state.cpp | 7 ++ Source/3rdParty/Luax/luax_state.h | 7 +- Source/3rdParty/Luax/luax_state.inl | 11 +- Source/Asura.Engine/Application.h | 4 +- Source/Asura.Engine/application.h | 4 +- Source/Asura.Engine/scripting/portable.hpp | 3 + Source/Samples/LuaxTest/script.lua | 22 +++- 10 files changed, 259 insertions(+), 31 deletions(-) (limited to 'Source') diff --git a/Source/3rdParty/Luax/luax_class.cpp b/Source/3rdParty/Luax/luax_class.cpp index 8c94248..155fd28 100644 --- a/Source/3rdParty/Luax/luax_class.cpp +++ b/Source/3rdParty/Luax/luax_class.cpp @@ -39,6 +39,30 @@ namespace Luax lua_pushvalue(L, -1); // class table lua_setfield(L, -2, "__index"); + lua_pushstring(L, type); + lua_pushcclosure(L, l___tostring, 1); + lua_setfield(L, -2, "__tostring"); + + return 1; + } + + int LuaxPlainClass::l___tostring(lua_State* L) + { + // upvalues: + // 1: class name + + // params: + // 1: instance + + if (!lua_istable(L, 1)) + { + return luaL_typerror(L, 1, lua_typename(L, LUA_TTABLE)); + } + + cc8* type = lua_tostring(L, lua_upvalueindex(1)); + + lua_pushfstring(L, "%s: %p", type, lua_topointer(L, 1)); + return 1; } @@ -64,8 +88,9 @@ namespace Luax lua_pushvalue(L, classTable); lua_setmetatable(L, -2); + // 找到构造函数,会触发metatable.__index,根据继承链向上找。 lua_getfield(L, classTable, "Ctor"); - if (!lua_isnil(L, -1)) + if (state.IsType(-1, LUA_TFUNCTION)) { // stack: // -1: Ctor() @@ -145,13 +170,17 @@ namespace Luax lua_pushcclosure(L, l_Extend, 1); lua_setfield(L, -2, "Extend"); - // .base 用来索引到基类 + // .__base 用来索引到基类 lua_pushvalue(L, baseClass); // base class lua_setfield(L, -2, "__base"); lua_pushvalue(L, -1); // class table lua_setfield(L, -2, "__index"); + lua_pushstring(L, type); + lua_pushcclosure(L, l___tostring, 1); + lua_setfield(L, -2, "__tostring"); + // class的metatable设置为baseClass lua_pushvalue(L, baseClass); lua_setmetatable(L, -2); diff --git a/Source/3rdParty/Luax/luax_class.hpp b/Source/3rdParty/Luax/luax_class.hpp index c196024..1689e0c 100644 --- a/Source/3rdParty/Luax/luax_class.hpp +++ b/Source/3rdParty/Luax/luax_class.hpp @@ -6,6 +6,7 @@ #include "luax_config.h" #include "luax_ref.h" #include "luax_memberref.h" +#include "luax_cfunctions.h" namespace Luax { @@ -117,15 +118,16 @@ namespace Luax // 公共内容 LUAX_DECL_METHOD( l___tostring ); + LUAX_DECL_METHOD( l_GetClass ); LUAX_DECL_METHOD( l_GetClassName ); //------------------------------------------------------------------------------------------------------------ // 工厂类相关 - LUAX_DECL_METHOD( l___gc ); - LUAX_DECL_METHOD( l_ExtendFactory ); - LUAX_DECL_METHOD( l_GetClass ); - LUAX_DECL_METHOD( l_GetRefTable ); + LUAX_DECL_METHOD( l___gc ); + LUAX_DECL_METHOD( l_ExtendFactory ); + LUAX_DECL_METHOD( l_GetRefTable ); + LUAX_DECL_METHOD( l_New ); //------------------------------------------------------------------------------------------------------------ // 单例类相关 @@ -148,8 +150,9 @@ namespace Luax /// static int registry(lua_State* L); - LUAX_DECL_METHOD( l_Extend ); - LUAX_DECL_METHOD( l_New ); + LUAX_DECL_METHOD( l___tostring ); + LUAX_DECL_METHOD( l_Extend ); + LUAX_DECL_METHOD( l_New ); }; diff --git a/Source/3rdParty/Luax/luax_class.inl b/Source/3rdParty/Luax/luax_class.inl index 666c1a3..48f1c1a 100644 --- a/Source/3rdParty/Luax/luax_class.inl +++ b/Source/3rdParty/Luax/luax_class.inl @@ -26,6 +26,7 @@ namespace Luax void LuaxNativeClass::RegisterLuaxClass(LuaxState& state) { luaL_Reg regTable[] = { + { "GetClass", l_GetClass }, { "GetClassName", l_GetClassName }, { NULL, NULL } }; @@ -40,7 +41,6 @@ namespace Luax void LuaxNativeClass::RegisterLuaxFactoryClass(LuaxState& state) { luaL_Reg regTable[] = { - { "GetClass", l_GetClass }, { "GetRefTable", l_GetRefTable }, { NULL, NULL } }; @@ -222,10 +222,7 @@ namespace Luax int memberTable = top - 1; int refTable = top - 2; - // ref table 注册 __gc 和 __tostring - lua_pushcfunction(state, l___gc); - lua_setfield(state, refTable, "__gc"); - + // ref table 注册 __tostring lua_pushcfunction(state, l___tostring); lua_setfield(state, refTable, "__tostring"); @@ -236,6 +233,9 @@ namespace Luax lua_pushvalue(state, memberTable); lua_setfield(state, refTable, "__newindex"); + lua_pushcfunction(state, l___gc); + lua_setfield(state, refTable, "__gc"); + // 设置元表 lua_setmetatable(state, -2); // class is meta of member lua_setmetatable(state, -2); // member is meta of ref @@ -308,7 +308,8 @@ namespace Luax int LuaxNativeClass::l___gc(lua_State* L) { LUAX_SETUP(L, "U"); - + T* self = state.GetLuaUserdata(1); + delete self; return 0; } @@ -319,12 +320,13 @@ namespace Luax template int LuaxNativeClass::l___tostring(lua_State* L) { + // params: + // 1: userdata + 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)) @@ -337,27 +339,112 @@ namespace Luax { classname = T::GetLuaxClassName(); } - sprintf(buf, fmt, self, classname); - lua_pushstring(L, buf); + lua_pushfstring(L, "%s: %p", classname, self); return 1; } return 0; } + /// + /// 派生出子类,在lua里对派生类的成员和行为进行重新设计,但是保证了userdata的统一。Native class的派生提供Ctor支持,在 + /// native实体创建后可以使用Ctor进行初始化,派生类拥有和基类一样的New参数列表,且native对象是一样的类型。 + /// template int LuaxNativeClass::l_ExtendFactory(lua_State* L) { + // upvalues: + // 1: base class + // params: + // 1: class name - return 0; + 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, l_ExtendFactory, 1); + lua_setfield(L, -2, "Extend"); + + // .New() + lua_pushvalue(L, inheritClass); + lua_getfield(L, baseClass, "New"); + lua_pushcclosure(L, 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 int LuaxNativeClass::l_ExtendSingleton(lua_State* L) { + // upvalues: + // 1: base class + // params: + // 1: class name - return 0; + 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, 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 @@ -382,6 +469,79 @@ namespace Luax return 1; } + template + int LuaxNativeClass::l_New(lua_State* L) + { + LUAX_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); + + // 尝试调用Ctor函数 + lua_getfield(L, lua_upvalueindex(1), "Ctor"); + + 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; + } + template LuaxStrongRef LuaxNativeClass::mClassTable; // class table template LuaxStrongRef LuaxNativeClass::mSingletonRefTable; // 单例 diff --git a/Source/3rdParty/Luax/luax_state.cpp b/Source/3rdParty/Luax/luax_state.cpp index 94ca148..b27825e 100644 --- a/Source/3rdParty/Luax/luax_state.cpp +++ b/Source/3rdParty/Luax/luax_state.cpp @@ -171,6 +171,13 @@ namespace Luax lua_pushlightuserdata(mState, (void*)value); } + void LuaxState::PushValues(int idx, int n) + { + idx = AbsIndex(idx); + for (int i = idx; i < idx + n; ++i) + lua_pushvalue(mState, i); + } + void LuaxState::Pop(int n /* = 1 */) { lua_pop(mState, n); diff --git a/Source/3rdParty/Luax/luax_state.h b/Source/3rdParty/Luax/luax_state.h index fee9d8a..71e2c5c 100644 --- a/Source/3rdParty/Luax/luax_state.h +++ b/Source/3rdParty/Luax/luax_state.h @@ -99,6 +99,11 @@ namespace Luax void Push(void* data, size_t size); void Push(const void* value); + /// + /// 将idx开始的n个push到栈顶,idx会被取正,n向上生长。 + /// + void PushValues(int idx, int n); + /// /// 以void** 的形式创建userdata,并将值设置为ptr /// @@ -108,7 +113,7 @@ namespace Luax void Settop(int idx); - template T* GetLuaUserdata(int idx); + template T* GetLuaUserdata(int idx = 1); //------------------------------------------------------------------------------------------------------------ diff --git a/Source/3rdParty/Luax/luax_state.inl b/Source/3rdParty/Luax/luax_state.inl index 63245bb..712eb1d 100644 --- a/Source/3rdParty/Luax/luax_state.inl +++ b/Source/3rdParty/Luax/luax_state.inl @@ -26,6 +26,7 @@ namespace Luax Pop(); _assertmethod(-1, "New"); + //_assertmethod(-1, "__gc"); #undef _assertmethod @@ -65,16 +66,18 @@ namespace Luax // class table. lua_newtable(L); LuaxNativeClass::RegisterLuaxClass(state); - LuaxNativeClass::RegisterLuaxFactoryClass(state); + LuaxNativeClass::RegisterLuaxSingletonClass(state); T::RegisterLuaxClass(state); LuaxNativeClass::SetLuaxClassTableRef(state, -1); - // class table的__index和__newindex指向自身 lua_pushvalue(state, -1); lua_setfield(state, -2, "__index"); - lua_pushvalue(state, -1); - lua_setfield(state, -2, "__newindex"); + + // .Extend() + lua_pushvalue(state, -1); // class table + lua_pushcclosure(state, LuaxNativeClass::l_ExtendSingleton, 1); + lua_setfield(state, -2, "Extend"); cc8* type = T::GetLuaxSingletonName(); SetField(top, type); diff --git a/Source/Asura.Engine/Application.h b/Source/Asura.Engine/Application.h index 08b3bea..a260cf8 100644 --- a/Source/Asura.Engine/Application.h +++ b/Source/Asura.Engine/Application.h @@ -1,8 +1,8 @@ #ifndef __ASURA_ENGINE_APPLICATION_H__ #define __ASURA_ENGINE_APPLICATION_H__ -#include "Scripting/Portable.h" -#include "Config.h" +#include "scripting/portable.hpp" +#include "config.h" namespace AsuraEngine { diff --git a/Source/Asura.Engine/application.h b/Source/Asura.Engine/application.h index 08b3bea..a260cf8 100644 --- a/Source/Asura.Engine/application.h +++ b/Source/Asura.Engine/application.h @@ -1,8 +1,8 @@ #ifndef __ASURA_ENGINE_APPLICATION_H__ #define __ASURA_ENGINE_APPLICATION_H__ -#include "Scripting/Portable.h" -#include "Config.h" +#include "scripting/portable.hpp" +#include "config.h" namespace AsuraEngine { diff --git a/Source/Asura.Engine/scripting/portable.hpp b/Source/Asura.Engine/scripting/portable.hpp index aeb1ed0..df0b878 100644 --- a/Source/Asura.Engine/scripting/portable.hpp +++ b/Source/Asura.Engine/scripting/portable.hpp @@ -10,6 +10,9 @@ namespace AsuraEngine namespace Scripting { + /// + /// 向lua注册的native class需要继承此类。 + /// template class Portable : public Luax::LuaxNativeClass { diff --git a/Source/Samples/LuaxTest/script.lua b/Source/Samples/LuaxTest/script.lua index df6cbdf..7bf9337 100644 --- a/Source/Samples/LuaxTest/script.lua +++ b/Source/Samples/LuaxTest/script.lua @@ -68,7 +68,7 @@ function main() local Foo = Asura.Class("Foo") Foo.Ctor = function(self, age, name, boy) self.age = age - self.name = boy:GetName() + self.name = name self.boy = boy end Foo.GetAge = function(self) @@ -91,7 +91,7 @@ function main() self.age = age - 1 self.name = boy:GetName() self.boy = boy - self.__base.Ctor(self, age, name, boy) + self.__base.Ctor(self, age, "Wangba", boy) end Coo.GetName = function(self) local name = self.__base.GetName(self) @@ -101,6 +101,8 @@ function main() print(coo2:GetAge()) print(coo2.GetClassName()) print(coo2:GetName()) + print(coo2) + print(coo) ---------------------plain enum test local ERace = Asura.Enum("ERace", { ["White"] = 1, @@ -109,6 +111,22 @@ function main() }) print(ERace.White) print(ERace.Asian) +----------------------native class inherit test + local Boy2 = Asura.SimBoy.Extend("Boy2") + Boy2.Speak = function(self) + return self.__base.GetAge(self) + end + Boy2.Ctor = function(self, age, name) + print("ctor " .. age) + print("ctor " .. name) + end + local boy22 = Boy2.New(12, "Liu") + print(boy22) + print(boy22:Speak()) + +------------------------gc test + local boy = Asura.SimBoy.New(11, "chaichai") + boy = nil end function err(msg) print(msg) -- cgit v1.1-26-g67d0