diff --git a/include/Nazara/Lua/LuaClass.hpp b/include/Nazara/Lua/LuaClass.hpp index 4f47f36f1..96e271a31 100644 --- a/include/Nazara/Lua/LuaClass.hpp +++ b/include/Nazara/Lua/LuaClass.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include //#include @@ -22,12 +23,12 @@ namespace Nz //static_assert(std::is_same::value || std::is_base_of::value, "P must be a base of T"); public: - using ClassFunc = int (*)(LuaInstance& lua, T& instance); - using ClassIndexFunc = bool (*)(LuaInstance& lua, T& instance); - using ConstructorFunc = T* (*)(LuaInstance& lua); - using FinalizerFunc = bool (*)(LuaInstance& lua, T& instance); - using StaticIndexFunc = bool (*)(LuaInstance& lua); - using StaticFunc = int (*)(LuaInstance& lua); + using ClassFunc = std::function; + using ClassIndexFunc = std::function; + using ConstructorFunc = std::function; + using FinalizerFunc = std::function; + using StaticIndexFunc = std::function; + using StaticFunc = std::function; LuaClass(const String& name); @@ -41,9 +42,12 @@ namespace Nz void SetFinalizer(FinalizerFunc finalizer); void SetGetter(ClassIndexFunc getter); void SetMethod(const String& name, ClassFunc method); + template std::enable_if_t::value> SetMethod(const String& name, R(P::*func)(Args...)); + template std::enable_if_t::value> SetMethod(const String& name, R(P::*func)(Args...) const); void SetSetter(ClassIndexFunc setter); void SetStaticGetter(StaticIndexFunc getter); void SetStaticMethod(const String& name, StaticFunc func); + template void SetStaticMethod(const String& name, R(*func)(Args...)); void SetStaticSetter(StaticIndexFunc getter); private: diff --git a/include/Nazara/Lua/LuaClass.inl b/include/Nazara/Lua/LuaClass.inl index 9fa445ffa..545fa08ba 100644 --- a/include/Nazara/Lua/LuaClass.inl +++ b/include/Nazara/Lua/LuaClass.inl @@ -174,6 +174,32 @@ namespace Nz { m_methods[name] = method; } + + template + template + std::enable_if_t::value> LuaClass::SetMethod(const String& name, R(P::*func)(Args...)) + { + SetMethod(name, [func] (LuaInstance& instance, T& object) -> int + { + LuaImplMethodProxy handler(instance, object); + handler.ProcessArgs(); + + return handler.Invoke(func); + }); + } + + template + template + std::enable_if_t::value> LuaClass::SetMethod(const String& name, R(P::*func)(Args...) const) + { + SetMethod(name, [func] (LuaInstance& instance, T& object) -> int + { + LuaImplMethodProxy handler(instance, object); + handler.ProcessArgs(); + + return handler.Invoke(func); + }); + } template void LuaClass::SetSetter(ClassIndexFunc setter) @@ -193,6 +219,19 @@ namespace Nz m_staticMethods[name] = method; } + template + template + void LuaClass::SetStaticMethod(const String& name, R(*func)(Args...)) + { + SetStaticMethod(name, [func] (LuaInstance& instance) -> int + { + LuaImplFunctionProxy handler(instance); + handler.ProcessArgs(); + + return handler.Invoke(func); + }); + } + template void LuaClass::SetStaticSetter(StaticIndexFunc setter) { diff --git a/include/Nazara/Lua/LuaInstance.hpp b/include/Nazara/Lua/LuaInstance.hpp index 24e9a4f7d..1124ce72a 100644 --- a/include/Nazara/Lua/LuaInstance.hpp +++ b/include/Nazara/Lua/LuaInstance.hpp @@ -42,6 +42,7 @@ namespace Nz bool Call(unsigned int argCount); bool Call(unsigned int argCount, unsigned int resultCount); + template T Check(int index); void CheckAny(int index) const; bool CheckBoolean(int index) const; bool CheckBoolean(int index, bool defValue) const; @@ -110,6 +111,7 @@ namespace Nz void Pop(unsigned int n = 1U); + template int Push(T arg); void PushBoolean(bool value); void PushCFunction(LuaCFunction func, unsigned int upvalueCount = 0); void PushFunction(LuaFunction func); diff --git a/include/Nazara/Lua/LuaInstance.inl b/include/Nazara/Lua/LuaInstance.inl index beef1fe6d..0274bb0be 100644 --- a/include/Nazara/Lua/LuaInstance.inl +++ b/include/Nazara/Lua/LuaInstance.inl @@ -23,9 +23,22 @@ namespace Nz return static_cast(instance.CheckNumber(index)); } - int LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) + template + std::enable_if_t::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { - return static_cast(instance.CheckInteger(index)); + return static_cast(LuaImplQueryArg(instance, index, TypeTag::type>())); + } + + template + std::enable_if_t::value && !std::is_unsigned::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) + { + return static_cast(instance.CheckInteger(index)); + } + + template + std::enable_if_t::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) + { + return static_cast(LuaImplQueryArg(instance, index, TypeTag::type>())); } std::string LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) @@ -50,51 +63,62 @@ namespace Nz return LuaImplQueryArg(instance, index, TypeTag()); } - template - std::enable_if_t::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) - { - return static_cast(LuaImplQueryArg(instance, index, TypeTag::type>())); - } - // Function returns - int LuaImplReplyVal(LuaInstance& instance, bool&& val, TypeTag) + int LuaImplReplyVal(LuaInstance& instance, bool val, TypeTag) { instance.PushBoolean(val); return 1; } - int LuaImplReplyVal(LuaInstance& instance, double&& val, TypeTag) + int LuaImplReplyVal(LuaInstance& instance, double val, TypeTag) { instance.PushNumber(val); return 1; } - int LuaImplReplyVal(LuaInstance& instance, float&& val, TypeTag) + int LuaImplReplyVal(LuaInstance& instance, float val, TypeTag) { instance.PushNumber(val); return 1; } - int LuaImplReplyVal(LuaInstance& instance, int&& val, TypeTag) + template + std::enable_if_t::value, int> LuaImplReplyVal(LuaInstance& instance, T val, TypeTag) + { + using EnumT = typename std::underlying_type::type; + + return LuaImplReplyVal(instance, static_cast(val), TypeTag()); + } + + template + std::enable_if_t::value && !std::is_unsigned::value, int> LuaImplReplyVal(LuaInstance& instance, T val, TypeTag) { instance.PushInteger(val); return 1; } - int LuaImplReplyVal(LuaInstance& instance, std::string&& val, TypeTag) + template + std::enable_if_t::value, int> LuaImplReplyVal(LuaInstance& instance, T val, TypeTag) + { + using SignedT = typename std::make_signed::type; + + return LuaImplReplyVal(instance, static_cast(val), TypeTag()); + } + + int LuaImplReplyVal(LuaInstance& instance, std::string val, TypeTag) { instance.PushString(val.c_str(), val.size()); return 1; } - int LuaImplReplyVal(LuaInstance& instance, String&& val, TypeTag) + int LuaImplReplyVal(LuaInstance& instance, String val, TypeTag) { instance.PushString(std::move(val)); return 1; } template - int LuaImplReplyVal(LuaInstance& instance, std::pair&& val, TypeTag>) + int LuaImplReplyVal(LuaInstance& instance, std::pair val, TypeTag>) { int retVal = 0; @@ -104,14 +128,6 @@ namespace Nz return retVal; } - template - std::enable_if_t::value, int> LuaImplReplyVal(LuaInstance& instance, T&& val, TypeTag) - { - using SignedT = typename std::make_signed::type; - - return LuaImplReplyVal(instance, val, TypeTag()); - } - template class LuaImplFunctionProxy { @@ -152,12 +168,89 @@ namespace Nz } private: - LuaInstance& m_instance; std::tuple m_args; + LuaInstance& m_instance; }; + template + class LuaImplMethodProxy + { + public: + LuaImplMethodProxy(LuaInstance& instance, T& object) : + m_instance(instance), + m_object(object) + { + } + + template + void ProcessArgs() + { + } + + template + void ProcessArgs() + { + std::get(m_args) = std::move(LuaImplQueryArg(m_instance, N + 1, TypeTag())); + } + + template + void ProcessArgs() + { + ProcessArgs(); + ProcessArgs(); + } + + void ProcessArgs() + { + ProcessArgs<0, Args...>(); + } + + template + std::enable_if_t::value, int> Invoke(void(P::*func)(Args...)) + { + Apply(m_object, func, m_args); + return 0; + } + + template + std::enable_if_t::value, int> Invoke(Ret(P::*func)(Args...)) + { + return LuaImplReplyVal(m_instance, std::move(Apply(m_object, func, m_args)), TypeTag()); + } + + template + std::enable_if_t::value, int> Invoke(void(P::*func)(Args...) const) + { + Apply(m_object, func, m_args); + return 0; + } + + template + std::enable_if_t::value, int> Invoke(Ret(P::*func)(Args...) const) + { + return LuaImplReplyVal(m_instance, std::move(Apply(m_object, func, m_args)), TypeTag()); + } + + private: + std::tuple m_args; + LuaInstance& m_instance; + T& m_object; + }; + + template + T LuaInstance::Check(int index) + { + return LuaImplQueryArg(*this, index, TypeTag()); + } + + template + int LuaInstance::Push(T arg) + { + return LuaImplReplyVal(*this, std::move(arg), TypeTag()); + } + template - void LuaInstance::PushFunction(R(*func)(Args...)) + void LuaInstance::PushFunction(R (*func)(Args...)) { PushFunction([func](LuaInstance& instance) -> int {