From 70b82d1981c0de3c7b77670ff8abcfeb26815142 Mon Sep 17 00:00:00 2001 From: chai Date: Tue, 12 Mar 2019 00:39:26 +0800 Subject: *misc --- Source/3rdParty/Luax/lua.hpp | 6 +- Source/3rdParty/Luax/luax.h | 40 ++- Source/3rdParty/Luax/luax_class.cpp | 50 +++ Source/3rdParty/Luax/luax_class.h | 124 ++++++-- Source/3rdParty/Luax/luax_class.inl | 76 +++++ Source/3rdParty/Luax/luax_config.h | 47 +++ Source/3rdParty/Luax/luax_ref.h | 27 ++ Source/3rdParty/Luax/luax_state.cpp | 606 +++++++++++++++++++++++++++++++++++- Source/3rdParty/Luax/luax_state.h | 166 +++++++++- Source/3rdParty/Luax/luax_state.inl | 110 +++++++ 10 files changed, 1198 insertions(+), 54 deletions(-) create mode 100644 Source/3rdParty/Luax/luax_class.inl create mode 100644 Source/3rdParty/Luax/luax_config.h create mode 100644 Source/3rdParty/Luax/luax_state.inl (limited to 'Source/3rdParty/Luax') diff --git a/Source/3rdParty/Luax/lua.hpp b/Source/3rdParty/Luax/lua.hpp index 2ad2293..ab14a19 100644 --- a/Source/3rdParty/Luax/lua.hpp +++ b/Source/3rdParty/Luax/lua.hpp @@ -4,8 +4,8 @@ // Include lua first extern "C" { -#include "lua.h" -#include "lualib.h" -#include "lauxlib.h" +#include "lua51/lua.h" +#include "lua51/lualib.h" +#include "lua51/lauxlib.h" } #endif \ No newline at end of file diff --git a/Source/3rdParty/Luax/luax.h b/Source/3rdParty/Luax/luax.h index 68ff9f2..66162a4 100644 --- a/Source/3rdParty/Luax/luax.h +++ b/Source/3rdParty/Luax/luax.h @@ -1,11 +1,8 @@ #ifndef __LUAX_H__ #define __LUAX_H__ -extern "C" { -#include "lua.h" -#include "lualib.h" -#include "lauxlib.h" -} +// 从moai-core中抽离出来 + // include lua.hpp before this #include "luax_runtime.h" #include "luax_state.h" @@ -17,5 +14,38 @@ extern "C" { // * modules // * class // * +/* + +GetClassName +GetClass +New +Extend +GetInterfaceTable + + + +__index +__newIndex +__gc +__mode +__tostring + + + +数据成员不需要允许访问(赋值和得到值),通过函数实现,即__index设置为元表 + +名称空间通过表实现 + +通过upvalue实现调用者的访问,而不需要通过传入self,比如通过BaseClass.Extend("SubClass")访问BaseClass,区分不同的base class, +把BaseClass设为Extend的upvalue,在cfunction通过lua_upvalueindex宏里访问upvalue。 + +之所以能通过.调用函数是因为元表,元表可以给userdata和table作为元表,所以userdata可以调用,但实际上不需要这样。 + +interface table -> member table +member table -> ref table +ref table -> userdata 保存了对每个其他类型的引用和引用计数(用hLuaUserdata作为key),计数是为了debug + +class table 是类型的本体(工厂),有New、Extend、GetClassName方法 +*/ #endif \ No newline at end of file diff --git a/Source/3rdParty/Luax/luax_class.cpp b/Source/3rdParty/Luax/luax_class.cpp index e69de29..99da697 100644 --- a/Source/3rdParty/Luax/luax_class.cpp +++ b/Source/3rdParty/Luax/luax_class.cpp @@ -0,0 +1,50 @@ +#include "luax_state.h" +#include "luax_class.h" + +namespace Luax +{ + + LuaxClass::LuaxClass() + : mRefCount(1) // 构造时默认有一个引用 + { + } + + LuaxClass::~LuaxClass() + { + } + + void LuaxClass::Retain() + { + ++mRefCount; + } + + void LuaxClass::Release() + { + if (--mRefCount <= 0) + delete this; + } + + bool LuaxClass::PushLuaUserdata(LuaxState& state) + { + return true; + } + + void LuaxClass::BindToLua(LuaxState& state) + { + assert(!mUserdata); + + } + + //-------------------------------------------------------------------------------------------------------------- + + /// + /// 释放工厂创建的实例 + /// + int LuaxClass::l_GC(lua_State* L) + { + LUAX_SETUP(L, "U"); + + return 0; + } + +} \ No newline at end of file diff --git a/Source/3rdParty/Luax/luax_class.h b/Source/3rdParty/Luax/luax_class.h index 1721ec4..d241030 100644 --- a/Source/3rdParty/Luax/luax_class.h +++ b/Source/3rdParty/Luax/luax_class.h @@ -3,50 +3,110 @@ #include +#include "lua.hpp" +#include "luax_config.h" +#include "luax_state.h" + namespace Luax { -#define LUAX_DECL_METHOD(MTD) static int MTD(lua_State*) -#define LUAX_DECL_FACTORY(CLS) static int RegisterLuaClass(lua_State*); -#define LUAX_DECL_SINGLETON(CLS) +#define LUAX_DECL_METHOD(mtd) static int mtd(lua_State*) + + /// + /// RegisterLuaxClass 注册类的方法和成员,比如枚举、常量等到class table + /// LuaxRegisterInterface 注册接口方法到interface table + /// LuaxGetFactoryName 获得工厂的类名,同时用来避免注册时错误注册为了singleton,通过编译时报错避免 + /// +#define LUAX_DECL_FACTORY(type) \ + static void RegisterLuaxClass(LuaxState&);\ + static void RegisterLuaxInterface(LuaxState&);\ + static const char* GetLuaxFactoryName() { return #type; };\ + static const char* GetLuaxClassName() { return #type; };\ + static bool IsLuaxClassSingleton() { return false; }; + + + /// + /// RegisterLuaxClass 注册类的方法和成员,比如枚举、常量等到class table + /// LuaxGetSingletonName 获得单例的类名 + /// +#define LUAX_DECL_SINGLETON(type) \ + static void RegisterLuaxClass(LuaxState&); \ + static const char* GetLuaxSingletonName() { return #type; }; \ + static const char* GetLuaxClassName() { return #type; }; \ + static bool IsLuaxClassSingleton() { return true; }; + + + /// + /// 需要暴露给lua的class需要继承此类。通过lua管理的实例要确保引用计数的正确性,在多个线程中需要确定不会误释放。 + /// + class LuaxClass + { + public: + + void Retain(); + void Release(); + + //------------------------------------------------------------------------------------------------------------ + // 公共内容 + + template + static void RegisterLuaxClass(LuaxState& state); + + template + LUAX_DECL_METHOD(l_GetClassName); + + //------------------------------------------------------------------------------------------------------------ + // 工厂类相关 + + template + static void RegisterLuaxFactoryClass(LuaxState& state); + + template + static void RegisterLuaxInterface(LuaxState& state); + + LUAX_DECL_METHOD(l_GC); + + //------------------------------------------------------------------------------------------------------------ + // 单例类相关 + + template + static void RegisterLuaxSingletonClass(LuaxState& state); + + protected: + + LuaxClass(); + ~LuaxClass(); -#define LUAX_REGISTER_CLASS(CLS) CLS::RegisterLuaType() - /* - /// - /// 需要暴露给lua的class需要继承此类。 - /// - class LuaxClass - { - public: + /// + /// 将userdata push到栈顶,如果没有初始化mUserdata,初始化设置好元表并把初始化好的userdata留在栈顶。 + /// + bool PushLuaUserdata(LuaxState& state); - static void RegisterLuaType(); + private: - static void RegisterLuaFuncs(); + /// + /// 屏蔽取地址运算符,如果需要地址,只能通过在堆上创建实例得到。在栈上和静态区的变量不能取地址。保证引用计数的准确。如 + /// 果需要穿引用,使用引用传递而不是传递地址。 + /// + void* operator &(); - private: - - }; + void BindToLua(LuaxState& state); - /// - /// 需要作为工厂创建userdata的类继承此类。成为工厂的类,通过LUAX_DECL_FACTORY(CLS)宏指定类名。 - /// - class LuaxFactory : public LuaxClass - { - + int mRefCount; - }; + void* mUserdata; + + }; - /// - /// 注入给lua的单例类继承此类。 - /// - class LuaxSingleton : public LuaxClass - { - public: + /// + /// 在成员方法里创建LuaxState并对参数进行检查。 + /// +#define LUAX_SETUP(L, params) \ + LuaxState state(L);\ + if(!state.CheckParams(1, params)) return 0; - private: +#include "luax_class.inl" - }; - */ } #endif \ No newline at end of file diff --git a/Source/3rdParty/Luax/luax_class.inl b/Source/3rdParty/Luax/luax_class.inl new file mode 100644 index 0000000..23d4c28 --- /dev/null +++ b/Source/3rdParty/Luax/luax_class.inl @@ -0,0 +1,76 @@ + +//---------------------------------------------------------------------------------------------------------------- +// 接口 + +/// +/// 对不同类型,通过调用GetLuaClassName获得类型名 +/// +template +int LuaxClass::l_GetClassName(lua_State* L) +{ + LUAX_SETUP(L, "*"); + + cc8* type = T::GetLuaxClassName(); + state.Push(type); + return 1; +} + +//---------------------------------------------------------------------------------------------------------------- + +/// +/// 注册工厂和单例共有的类成员 +/// +template +void LuaxClass::RegisterLuaxClass(LuaxState& state) +{ + luaL_Reg regTable[] = { + { "GetClassName", l_GetClassName }, + { NULL, NULL } + }; + + state.Register(regTable); +} + + +/// +/// 工厂类的成员,注册在class table +/// +template +void LuaxClass::RegisterLuaxFactoryClass(LuaxState& state) +{ + luaL_Reg regTable[] = { + { "Extend", l_ExtendFactory }, + { NULL, NULL } + }; + + state.Register(regTable); +} + + +/// +/// 工厂实例的成员,注册在interface table +/// +template +void LuaxClass::RegisterLuaxInterface(LuaxState& state) +{ + luaL_Reg regTable[] = { + { "__gc", l_GC }, + { NULL, NULL } + }; + + state.Register(regTable); +} + + +/// +/// 单例类的成员,注册在class table +/// +template +void LuaxClass::RegisterLuaxSingletonClass(LuaxState& state) +{ + luaL_Reg regTable[] = { + {NULL, NULL} + }; + + state.Register(regTable); +} \ No newline at end of file diff --git a/Source/3rdParty/Luax/luax_config.h b/Source/3rdParty/Luax/luax_config.h new file mode 100644 index 0000000..a33750f --- /dev/null +++ b/Source/3rdParty/Luax/luax_config.h @@ -0,0 +1,47 @@ +#ifndef __LUAX_TYPE_H__ +#define __LUAX_TYPE_H__ + +#include + +namespace Luax +{ + + typedef unsigned int uint; + typedef unsigned long uintptr; + typedef long sintptr; + + typedef const char cc8; + + typedef unsigned char u8; + typedef unsigned short u16; + typedef unsigned int u32; + typedef unsigned long long u64; + + typedef signed char s8; + typedef signed short s16; + typedef signed int s32; + typedef signed long long s64; + +#ifdef _WIN32 + #define LUAX_FINAL final + #define LUAX_LIBRARY_EXPORT __declspec(dllexport) + #define LUAX_LIBRARY_IMPORT __declspec(dllimport) + #define LUAX_FORCE_INLINE __forceinline + #define LUAX_RESTRICT __restrict + #define LUAX_ATTRIBUTE_USED + #define LUAX_ABSTRACT + #define LUAX_API LUAX_LIBRARY_EXPORT +#else + #define LUAX_FINAL final + #define LUAX_LIBRARY_EXPORT __attribute__((visibility("default"))) + #define LUAX_LIBRARY_IMPORT + #define LUAX_FORCE_INLINE __attribute__((always_inline)) inline + #define LUAX_RESTRICT __restrict__ + #define LUAX_ATTRIBUTE_USED __attribute__((used)) + #define LUAX_ABSTRACT + #define LUAX_API LUAX_LIBRARY_EXPORT +#endif + +} + +#endif \ No newline at end of file diff --git a/Source/3rdParty/Luax/luax_ref.h b/Source/3rdParty/Luax/luax_ref.h index e69de29..122c448 100644 --- a/Source/3rdParty/Luax/luax_ref.h +++ b/Source/3rdParty/Luax/luax_ref.h @@ -0,0 +1,27 @@ +#ifndef __LUAX_REF_H__ +#define __LUAX_REF_H__ + +namespace Luax +{ + + /// + /// Lua reference,保存在LUA_REGISTRYINDEX寄存器里面。 + /// + class LuaxRef + { + + }; + + class LuaxStrongRef: public LuaxRef + { + + }; + + class LuaxWeakRef : public LuaxRef + { + + }; + +} + +#endif \ No newline at end of file diff --git a/Source/3rdParty/Luax/luax_state.cpp b/Source/3rdParty/Luax/luax_state.cpp index 3fc1645..a92d697 100644 --- a/Source/3rdParty/Luax/luax_state.cpp +++ b/Source/3rdParty/Luax/luax_state.cpp @@ -1,8 +1,612 @@ -//#include "luax_state.h" +#include "luax_state.h" namespace Luax { + +#define L mState + LuaxState::LuaxState(lua_State* state) + : L(state) + { + assert(state); + } + LuaxState::~LuaxState() + { + } + + LuaxState::operator lua_State*() + { + return L; + }; + + LuaxState::operator bool() + { + return L != nullptr; + } + + lua_State* LuaxState::operator ->() + { + return L; + } + + lua_State& LuaxState::operator*() + { + return *L; + } + + void LuaxState::OpenLibs() + { + luaL_openlibs(L); + } + + void LuaxState::PushNamespace(cc8* name) + { + bool isG = !lua_istable(L, -1); + int idx = isG ? LUA_GLOBALSINDEX : -1; + lua_getfield(L, idx, name); + if (lua_isnil(L, -1)) + { + lua_pop(L, 1); + lua_newtable(L); + assert(lua_istable(L, -1)); + lua_pushvalue(L, -1); + int t = isG ? LUA_GLOBALSINDEX : -3; + lua_setfield(L, t, name); + } + + // stack: + // -1 namespace + } + + void LuaxState::PopNamespace() + { + assert(lua_istable(L, -1)); + lua_pop(L, 1); + } + + void LuaxState::DoString(const std::string& code) + { + luaL_dostring(L, code.c_str()); + } + + int LuaxState::AbsIndex(int idx) + { + if (idx < 0) { + return lua_gettop(L) + idx + 1; + } + return idx; + } + + int LuaxState::Call(int nArgs, int nResults) + { + return 0; + } + + void LuaxState::Push() + { + lua_pushnil(L); + } + + void LuaxState::Push(bool value) + { + lua_pushboolean(L, value ? 1 : 0); + } + + void LuaxState::Push(cc8* value) + { + lua_pushstring(L, value); + } + + void LuaxState::Push(double value) + { + lua_pushnumber(L, value); + } + + void LuaxState::Push(float value) + { + lua_pushnumber(L, value); + } + + void LuaxState::Push(int value) + { + lua_pushnumber(L, value); + } + + void LuaxState::Push(u16 value) + { + lua_pushnumber(L, value); + } + + void LuaxState::Push(u32 value) + { + lua_pushnumber(L, value); + } + + void LuaxState::Push(u64 value) + { + lua_pushnumber(L, (double)value); + } + + void LuaxState::Push(uintptr value) + { + lua_pushlightuserdata(L, (void*)value); + } + + void LuaxState::Push(lua_CFunction value) + { + lua_pushcfunction(L, value); + } + + void LuaxState::Push(void* data, size_t size) + { + lua_pushlstring(L, (cc8*)data, size); + } + + void LuaxState::Push(const void* value) + { + lua_pushlightuserdata(L, (void*)value); + } + + void LuaxState::Pop(int n /* = 1 */) + { + lua_pop(L, n); + } + + bool LuaxState::IsNil(int idx) + { + return lua_isnil(L, idx); + } + + bool LuaxState::IsNilOrNone(int idx) + { + int t = lua_type(L, idx); + return ((t == LUA_TNONE) || (t == LUA_TNIL)); + } + + bool LuaxState::IsTableOrUserdata(int idx) + { + int check = lua_type(L, idx); + return ((check == LUA_TTABLE) || (check == LUA_TUSERDATA)); + } + + bool LuaxState::IsTrueOrNotNil(int idx) + { + if (lua_isboolean(L, idx)) { + return lua_toboolean(L, idx) ? true : false; + } + return !lua_isnil(L, idx); + } + + bool LuaxState::IsType(int idx, int type) + { + return (lua_type(L, idx) == type); + } + + bool LuaxState::IsType(int idx, cc8* name, int type) + { + return this->HasField(idx, name, type); + } + + bool LuaxState::IsValid() + { + return (L != 0); + } + + int LuaxState::GetTop() + { + return lua_gettop(mState); + } + + bool LuaxState::HasField(int idx, cc8* name) { + + lua_getfield(L, idx, name); + bool hasField = (lua_isnil(L, -1) == false); + lua_pop(L, 1); + + return hasField; + } + + bool LuaxState::HasField(int idx, int key) { + + this->GetField(idx, key); + bool hasField = (lua_isnil(L, -1) == false); + lua_pop(L, 1); + + return hasField; + } + + bool LuaxState::HasField(int idx, cc8* name, int type) { + + lua_getfield(L, idx, name); + bool hasField = (lua_type(L, -1) == type); + lua_pop(L, 1); + + return hasField; + } + + bool LuaxState::HasField(int idx, int key, int type) { + + this->GetField(idx, key); + bool hasField = (lua_type(L, -1) == type); + lua_pop(L, 1); + + return hasField; + } + + bool LuaxState::HasKeys(int idx) { + + idx = this->AbsIndex(idx); + + lua_pushnil(L); /* first key */ + if (lua_next(L, idx) != 0) { + lua_pop(L, 2); + return true; + } + return false; + } + + void LuaxState::Register(const luaL_Reg *l) + { + luaL_register(L, 0, l); + } + + void LuaxState::GetField(int idx, cc8* name) + { + lua_getfield(L, idx, name); + } + + void LuaxState::GetField(int idx, int key) + { + idx = this->AbsIndex(idx); + + lua_pushinteger(L, key); + lua_gettable(L, idx); + } + + std::string LuaxState::GetField(int idx, cc8* key, cc8* value) + { + std::string str; + if (this->GetFieldWithType(idx, key, LUA_TSTRING)) { + str = lua_tostring(L, -1); + lua_pop(L, 1); + } + else { + str = value; + } + return str; + } + + std::string LuaxState::GetField(int idx, int key, cc8* value) + { + std::string str; + if (this->GetFieldWithType(idx, key, LUA_TSTRING)) { + str = lua_tostring(L, -1); + lua_pop(L, 1); + } + else { + str = value; + } + return str; + } + + std::string LuaxState::GetField(int idx, cc8* key, const std::string& value) + { + std::string str; + if (this->GetFieldWithType(idx, key, LUA_TSTRING)) { + str = lua_tostring(L, -1); + lua_pop(L, 1); + } + else { + str = value; + } + return str; + } + + std::string LuaxState::GetField(int idx, int key, const std::string& value) + { + std::string str; + if (this->GetFieldWithType(idx, key, LUA_TSTRING)) { + str = lua_tostring(L, -1); + lua_pop(L, 1); + } + else { + str = value; + } + return str; + } + + bool LuaxState::GetFieldWithType(int idx, cc8* name, int type) + { + lua_getfield(L, idx, name); + if (lua_type(L, -1) != type) { + lua_pop(L, 1); + return false; + } + return true; + } + + bool LuaxState::GetFieldWithType(int idx, int key, int type) + { + this->GetField(idx, key); + if (lua_type(L, -1) != type) { + lua_pop(L, 1); + return false; + } + return true; + } + + void LuaxState::SetField(int idx, cc8* key) + { + if (IsTableOrUserdata(idx)) + { + idx = AbsIndex(idx); + lua_setfield(L, idx, key); + } + } + + cc8* LuaxState::GetLuaTypeName(int type) + { + switch (type) { + case LUA_TNONE: return "none"; + case LUA_TNIL: return "nil"; + case LUA_TBOOLEAN: return "boolean"; + case LUA_TLIGHTUSERDATA: return "lightuserdata"; + case LUA_TNUMBER: return "number"; + case LUA_TSTRING: return "string"; + case LUA_TTABLE: return "table"; + case LUA_TFUNCTION: return "function"; + case LUA_TUSERDATA: return "userdata"; + case LUA_TTHREAD: return "thread"; + } + return "unknown"; + } + + + bool LuaxState::GetSubfieldWithType(int idx, cc8* format, int type, ...) + { + va_list args; + va_start(args, type); + + idx = this->AbsIndex(idx); + lua_pushvalue(this->mState, idx); + + for (cc8* c = format; *c; ++c) { + switch (*c) { + // number + case 'N': + lua_pushnumber(this->mState, va_arg(args, int)); + lua_gettable(this->mState, -1); + break; + + // string + case 'S': + lua_getfield(this->mState, -1, va_arg(args, char*)); + break; + + default: + lua_pushnil(this->mState); + } + + if (lua_isnil(this->mState, -1)) break; + lua_replace(this->mState, -2); + } + va_end(args); + if (lua_type(this->mState, -1) != type) { + lua_pop(this->mState, 1); + return false; + } + return true; + } + + bool LuaxState::CheckParams(int idx, cc8* format) + { + idx = AbsIndex(idx); + + for (int i = 0; format[i]; ++i) { + + int pos = idx + i; + int type = LUA_TNIL; + int expected = LUA_TNONE; + + if (pos <= GetTop()) { + type = lua_type(mState, pos); + } + + switch (format[i]) { + + // boolean + case 'B': + if (type != LUA_TBOOLEAN) expected = LUA_TBOOLEAN; + break; + + // coroutine + case 'C': + if (type != LUA_TTHREAD) expected = LUA_TTHREAD; + break; + + // function + case 'F': + if (type != LUA_TFUNCTION) expected = LUA_TFUNCTION; + break; + + // light userdata + case 'L': + if (type != LUA_TLIGHTUSERDATA) expected = LUA_TLIGHTUSERDATA; + break; + + // number + case 'N': + if (type != LUA_TNUMBER) expected = LUA_TNUMBER; + break; + + // string + case 'S': + if (type != LUA_TSTRING) expected = LUA_TSTRING; + break; + + // table + case 'T': + if (type != LUA_TTABLE) expected = LUA_TTABLE; + break; + + // userdata + case 'U': + if (type != LUA_TUSERDATA) expected = LUA_TUSERDATA; + break; + + // any type + case '*': + case '.': + break; + } + + if (expected != LUA_TNONE) { + return false; + } + } + + return true; + } + + template <> + bool LuaxState::GetValue < bool >(int idx, const bool value) { + + if (this->IsType(idx, LUA_TBOOLEAN)) { + return (lua_toboolean(this->mState, idx) != 0); + } + return value; + } + + + template <> + cc8* LuaxState::GetValue < cc8* >(int idx, const cc8* value) { + + if (this->IsType(idx, LUA_TSTRING)) { + return lua_tostring(this->mState, idx); + } + return value; + } + + template <> + std::string LuaxState::GetValue(int idx, const std::string value) + { + std::string str; + if (lua_type(this->mState, idx) == LUA_TSTRING) { + str = lua_tostring(this->mState, idx); + } + else { + str = value; + } + return str; + } + + template <> + double LuaxState::GetValue < double >(int idx, const double value) + { + if (this->IsType(idx, LUA_TNUMBER)) { + return lua_tonumber(this->mState, idx); + } + return value; + } + + template <> + float LuaxState::GetValue < float >(int idx, const float value) + { + if (this->IsType(idx, LUA_TNUMBER)) { + return (float)lua_tonumber(this->mState, idx); + } + return value; + } + + template <> + s8 LuaxState::GetValue < s8 >(int idx, const s8 value) + { + if (this->IsType(idx, LUA_TNUMBER)) { + return (s8)lua_tonumber(this->mState, idx); + } + return value; + } + + + template <> + s16 LuaxState::GetValue < s16 >(int idx, const s16 value) + { + if (this->IsType(idx, LUA_TNUMBER)) { + return (s16)lua_tonumber(this->mState, idx); + } + return value; + } + + + template <> + s32 LuaxState::GetValue < s32 >(int idx, const s32 value) + { + if (this->IsType(idx, LUA_TNUMBER)) { + return (s32)lua_tonumber(this->mState, idx); + } + return value; + } + + template <> + s64 LuaxState::GetValue < s64 >(int idx, const s64 value) + { + if (this->IsType(idx, LUA_TNUMBER)) { + return (s64)lua_tonumber(this->mState, idx); + } + return value; + } + + template <> + u8 LuaxState::GetValue < u8 >(int idx, const u8 value) + { + if (this->IsType(idx, LUA_TNUMBER)) { + return (u8)lua_tonumber(this->mState, idx); + } + return value; + } + + template <> + u16 LuaxState::GetValue < u16 >(int idx, const u16 value) + { + if (this->IsType(idx, LUA_TNUMBER)) { + return (u16)lua_tonumber(this->mState, idx); + } + return value; + } + + template <> + u32 LuaxState::GetValue < u32 >(int idx, const u32 value) + { + if (this->IsType(idx, LUA_TNUMBER)) { + return (u32)lua_tonumber(this->mState, idx); + } + return value; + } + + template <> + u64 LuaxState::GetValue < u64 >(int idx, const u64 value) + { + if (this->IsType(idx, LUA_TNUMBER)) { + return (u64)lua_tonumber(this->mState, idx); + } + return value; + } + + template <> + const void* LuaxState::GetValue < const void* >(int idx, const void* value) + { + if (this->IsType(idx, LUA_TLIGHTUSERDATA)) { + return (void*)lua_touserdata(this->mState, idx); + } + return value; + } + + void LuaxState::PushPtrUserData(void* ptr) { + + void** handle = (void**)lua_newuserdata(this->mState, sizeof(void*)); + assert(handle); + (*handle) = ptr; + } } \ No newline at end of file diff --git a/Source/3rdParty/Luax/luax_state.h b/Source/3rdParty/Luax/luax_state.h index 7b6338f..52b8f38 100644 --- a/Source/3rdParty/Luax/luax_state.h +++ b/Source/3rdParty/Luax/luax_state.h @@ -1,26 +1,166 @@ #ifndef __LUAX_STATE_H__ #define __LUAX_STATE_H__ +#include + +#include "lua.hpp" +#include "luax_config.h" + namespace Luax { - class LuaxState - { - public: - LuaxState(lua_State* state) : mState(state){}; - ~LuaxState() {}; + class LuaxClass; + + /// + /// 对lua_State的代理,除了保存一个lua_State的引用不保存其他内容。一个实例的metatable如下: + /// interface table + /// member table + /// ref table + /// userdata + /// 从userdata通过getmetatable获取上级metatable。除此之外还有一个class table注册在对应的名称空间里。 + /// + LUAX_API class LuaxState + { + public: + + LuaxState(lua_State* state); + ~LuaxState(); + + operator lua_State*(); + operator bool(); + lua_State* operator ->(); + lua_State& operator *(); + + //------------------------------------------------------------------------------------------------------------ + + void OpenLibs(); + + //------------------------------------------------------------------------------------------------------------ + // 名称空间管理,名称空间就是一个表,_G是最上面的表 + + void PushNamespace(cc8* name); + void PopNamespace(); + + //------------------------------------------------------------------------------------------------------------ + + int GetTop(); + bool CheckParams(int idx, cc8* format); + int AbsIndex(int idx); + int Call(int nArgs, int nResults); + + //------------------------------------------------------------------------------------------------------------ + + /// + /// 注册C函数,注意后面加一行{0, 0} + /// + void Register(const luaL_Reg *l); + + void GetField(int idx, cc8* name); + void GetField(int idx, int key); + std::string GetField(int idx, cc8* key, cc8* value); + std::string GetField(int idx, int key, cc8* value); + std::string GetField(int idx, cc8* key, const std::string& value); + std::string GetField(int idx, int key, const std::string& value); + bool GetFieldWithType(int idx, cc8* name, int type); + bool GetFieldWithType(int idx, int key, int type); + bool GetSubfieldWithType(int idx, cc8* format, int type, ...); + static cc8* GetLuaTypeName(int type); + + void SetField(int idx, cc8* key); + + bool IsNil(int idx); + bool IsNilOrNone(int idx); + bool IsTableOrUserdata(int idx); + bool IsTrueOrNotNil(int idx); + bool IsType(int idx, int type); + bool IsType(int idx, cc8* name, int type); + bool IsValid(); + + bool HasField(int idx, cc8* name); + bool HasField(int idx, int key); + bool HasField(int idx, cc8* name, int type); + bool HasField(int idx, int name, int type); + bool HasKeys(int idx); + + void Push(); + void Push(bool value); + void Push(cc8* value); + void Push(double value); + void Push(float value); + void Push(int value); + void Push(u16 value); + void Push(u32 value); + void Push(u64 value); + void Push(uintptr value); + void Push(lua_CFunction value); + void Push(void* data, size_t size); + void Push(const void* value); + + /// + /// 以void** 的形式创建userdata,并将值设置为ptr + /// + void PushPtrUserData(void* ptr); + + void Pop(int n = 1); + + //------------------------------------------------------------------------------------------------------------ + + template T GetValue(int idx, T default_value); + template T GetField(int idx, int key, T value); + template T GetField(int idx, cc8* key, T value); + template void SetField(int idx, cc8* key, T value); + template void SetFieldByIndex(int idx, int key, T value); + + //------------------------------------------------------------------------------------------------------------ + + void DoString(const std::string& code); + void DoFile(const std::string& file); + + //------------------------------------------------------------------------------------------------------------ + + /// + /// 注册工厂,适用于普通类,有New方法 + /// + template + void RegisterFactory(); + + /// + /// 注册单例,没有New方法 + /// + template + void RegisterSingleton(); + + private: + + /// + /// 屏蔽对LuaxState的地址相关操作 + /// + void* operator &(); + void* operator new(size_t size); + + lua_State* const mState; - inline operator lua_State*() { return mState; }; - operator bool(); - inline lua_State* operator ->() { return mState; }; - inline lua_State& operator *() { return *mState; }; + }; - private: - void* operator new(size_t size); +#include "luax_state.inl" - lua_State* mState; + //-------------------------------------------------------------------------------------------------------------- + // GetValue()模板特化 - }; + template <> bool LuaxState::GetValue < bool >(int idx, const bool value); + template <> cc8* LuaxState::GetValue < cc8* >(int idx, const cc8* value); + template <> double LuaxState::GetValue < double >(int idx, const double value); + template <> float LuaxState::GetValue < float >(int idx, const float value); + template <> s8 LuaxState::GetValue < s8 >(int idx, const s8 value); + template <> s16 LuaxState::GetValue < s16 >(int idx, const s16 value); + template <> s32 LuaxState::GetValue < s32 >(int idx, const s32 value); + template <> s64 LuaxState::GetValue < s64 >(int idx, const s64 value); + template <> u8 LuaxState::GetValue < u8 >(int idx, const u8 value); + template <> u16 LuaxState::GetValue < u16 >(int idx, const u16 value); + template <> u32 LuaxState::GetValue < u32 >(int idx, const u32 value); + template <> u64 LuaxState::GetValue < u64 >(int idx, const u64 value); + template <> std::string LuaxState::GetValue < std::string >(int idx, const std::string value); + template <> const void* LuaxState::GetValue < const void* >(int idx, const void* value); } diff --git a/Source/3rdParty/Luax/luax_state.inl b/Source/3rdParty/Luax/luax_state.inl new file mode 100644 index 0000000..1515123 --- /dev/null +++ b/Source/3rdParty/Luax/luax_state.inl @@ -0,0 +1,110 @@ + +// 针对普通类和单例类有不同的注册过程,通过LuaxState的两个工厂方法Register_实现 + +// 注册工厂,分为注册interface table和class table,以type name为键设置在名称空间上。在注册阶段不会设置元表,等到New方法调用的时候才会。 + +template +void LuaxState::RegisterFactory() +{ + lua_State* L = mState; + + int top = lua_gettop(L); // namespace table + + const char* type = T::GetLuaxFactoryName(); + + // interface table. + lua_newtable(L); + + int idx = AbsIndex(-1); + + LuaxClass::RegisterLuaxInterface(*this); + T::RegisterLuaxInterface(*this); + + // 检测T里面是否没有注册必须的方法 +#define assertMethods(I, NAME)\ + GetField(I, NAME);\ + assert(IsType(-1, LUA_TFUNCTION));\ + Pop(); + + assertMethods(idx, "New"); + +#undef assertMethods + + lua_settop(L, top); + + // class table. + lua_newtable(L); + + assert(lua_istable(L, -1)); + + lua_pushvalue(L, -1); + + LuaxClass::RegisterLuaxClass(*this); + LuaxClass::RegisterLuaxFactoryClass(*this); + T::RegisterLuaxClass(*this); + + SetField(top, type); + + // reset top + lua_settop(L, top); + +} + +// 注册单例 +template +void LuaxState::RegisterSingleton() +{ + lua_State* L = mState; + + int top = lua_gettop(L); // namespace table + + const char* type = T::GetLuaxSingletonName(); + + // class table. + lua_newtable(L); + + assert(lua_istable(L, -1)); + + lua_pushvalue(L, -1); + + LuaxClass::RegisterLuaxClass(*this); + LuaxClass::RegisterLuaxFactoryClass(*this); + T::RegisterLuaxClass(*this); + + SetField(top, type); + + // reset top + lua_settop(L, top); + +} + +template +void LuaxState::SetField(int idx, cc8* key, T value) +{ + if (IsTableOrUserdata(idx)) + { + idx = AbsIndex(idx); + this->Push(value); + lua_setfield(mState, idx, key); + } +} + +template +T LuaxState::GetField(int idx, cc8* key, T value) +{ + GetField(idx, key); + T result = GetValue < T >(-1, value); + this->Pop(); + + return result; +} + +template +T LuaxState::GetField(int idx, int key, T value) +{ + GetField(idx, key); + T result = GetValue < T >(-1, value); + Pop(); + + return result; +} -- cgit v1.1-26-g67d0