Lua: Add automatic method binding
Former-commit-id: fccd5f3682f6581db6b6b5976f4d0d3e0afa324c
This commit is contained in:
parent
6bc285cb00
commit
8915619934
|
|
@ -10,6 +10,7 @@
|
||||||
#include <Nazara/Prerequesites.hpp>
|
#include <Nazara/Prerequesites.hpp>
|
||||||
#include <Nazara/Core/String.hpp>
|
#include <Nazara/Core/String.hpp>
|
||||||
#include <Nazara/Lua/LuaInstance.hpp>
|
#include <Nazara/Lua/LuaInstance.hpp>
|
||||||
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
//#include <type_traits>
|
//#include <type_traits>
|
||||||
|
|
@ -22,12 +23,12 @@ namespace Nz
|
||||||
//static_assert(std::is_same<P, void>::value || std::is_base_of<P, T>::value, "P must be a base of T");
|
//static_assert(std::is_same<P, void>::value || std::is_base_of<P, T>::value, "P must be a base of T");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using ClassFunc = int (*)(LuaInstance& lua, T& instance);
|
using ClassFunc = std::function<int(LuaInstance& lua, T& instance)>;
|
||||||
using ClassIndexFunc = bool (*)(LuaInstance& lua, T& instance);
|
using ClassIndexFunc = std::function<bool(LuaInstance& lua, T& instance)>;
|
||||||
using ConstructorFunc = T* (*)(LuaInstance& lua);
|
using ConstructorFunc = std::function<T*(LuaInstance& lua)>;
|
||||||
using FinalizerFunc = bool (*)(LuaInstance& lua, T& instance);
|
using FinalizerFunc = std::function<bool(LuaInstance& lua, T& instance)>;
|
||||||
using StaticIndexFunc = bool (*)(LuaInstance& lua);
|
using StaticIndexFunc = std::function<bool(LuaInstance& lua)>;
|
||||||
using StaticFunc = int (*)(LuaInstance& lua);
|
using StaticFunc = std::function<int(LuaInstance& lua)>;
|
||||||
|
|
||||||
LuaClass(const String& name);
|
LuaClass(const String& name);
|
||||||
|
|
||||||
|
|
@ -41,9 +42,12 @@ namespace Nz
|
||||||
void SetFinalizer(FinalizerFunc finalizer);
|
void SetFinalizer(FinalizerFunc finalizer);
|
||||||
void SetGetter(ClassIndexFunc getter);
|
void SetGetter(ClassIndexFunc getter);
|
||||||
void SetMethod(const String& name, ClassFunc method);
|
void SetMethod(const String& name, ClassFunc method);
|
||||||
|
template<typename R, typename P, typename... Args> std::enable_if_t<std::is_base_of<P, T>::value> SetMethod(const String& name, R(P::*func)(Args...));
|
||||||
|
template<typename R, typename P, typename... Args> std::enable_if_t<std::is_base_of<P, T>::value> SetMethod(const String& name, R(P::*func)(Args...) const);
|
||||||
void SetSetter(ClassIndexFunc setter);
|
void SetSetter(ClassIndexFunc setter);
|
||||||
void SetStaticGetter(StaticIndexFunc getter);
|
void SetStaticGetter(StaticIndexFunc getter);
|
||||||
void SetStaticMethod(const String& name, StaticFunc func);
|
void SetStaticMethod(const String& name, StaticFunc func);
|
||||||
|
template<typename R, typename... Args> void SetStaticMethod(const String& name, R(*func)(Args...));
|
||||||
void SetStaticSetter(StaticIndexFunc getter);
|
void SetStaticSetter(StaticIndexFunc getter);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -175,6 +175,32 @@ namespace Nz
|
||||||
m_methods[name] = method;
|
m_methods[name] = method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
template<typename R, typename P, typename... Args>
|
||||||
|
std::enable_if_t<std::is_base_of<P, T>::value> LuaClass<T>::SetMethod(const String& name, R(P::*func)(Args...))
|
||||||
|
{
|
||||||
|
SetMethod(name, [func] (LuaInstance& instance, T& object) -> int
|
||||||
|
{
|
||||||
|
LuaImplMethodProxy<T, Args...> handler(instance, object);
|
||||||
|
handler.ProcessArgs();
|
||||||
|
|
||||||
|
return handler.Invoke(func);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
template<typename R, typename P, typename... Args>
|
||||||
|
std::enable_if_t<std::is_base_of<P, T>::value> LuaClass<T>::SetMethod(const String& name, R(P::*func)(Args...) const)
|
||||||
|
{
|
||||||
|
SetMethod(name, [func] (LuaInstance& instance, T& object) -> int
|
||||||
|
{
|
||||||
|
LuaImplMethodProxy<T, Args...> handler(instance, object);
|
||||||
|
handler.ProcessArgs();
|
||||||
|
|
||||||
|
return handler.Invoke(func);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void LuaClass<T>::SetSetter(ClassIndexFunc setter)
|
void LuaClass<T>::SetSetter(ClassIndexFunc setter)
|
||||||
{
|
{
|
||||||
|
|
@ -193,6 +219,19 @@ namespace Nz
|
||||||
m_staticMethods[name] = method;
|
m_staticMethods[name] = method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
template<typename R, typename... Args>
|
||||||
|
void LuaClass<T>::SetStaticMethod(const String& name, R(*func)(Args...))
|
||||||
|
{
|
||||||
|
SetStaticMethod(name, [func] (LuaInstance& instance) -> int
|
||||||
|
{
|
||||||
|
LuaImplFunctionProxy<Args...> handler(instance);
|
||||||
|
handler.ProcessArgs();
|
||||||
|
|
||||||
|
return handler.Invoke(func);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
void LuaClass<T>::SetStaticSetter(StaticIndexFunc setter)
|
void LuaClass<T>::SetStaticSetter(StaticIndexFunc setter)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ namespace Nz
|
||||||
bool Call(unsigned int argCount);
|
bool Call(unsigned int argCount);
|
||||||
bool Call(unsigned int argCount, unsigned int resultCount);
|
bool Call(unsigned int argCount, unsigned int resultCount);
|
||||||
|
|
||||||
|
template<typename T> T Check(int index);
|
||||||
void CheckAny(int index) const;
|
void CheckAny(int index) const;
|
||||||
bool CheckBoolean(int index) const;
|
bool CheckBoolean(int index) const;
|
||||||
bool CheckBoolean(int index, bool defValue) const;
|
bool CheckBoolean(int index, bool defValue) const;
|
||||||
|
|
@ -110,6 +111,7 @@ namespace Nz
|
||||||
|
|
||||||
void Pop(unsigned int n = 1U);
|
void Pop(unsigned int n = 1U);
|
||||||
|
|
||||||
|
template<typename T> int Push(T arg);
|
||||||
void PushBoolean(bool value);
|
void PushBoolean(bool value);
|
||||||
void PushCFunction(LuaCFunction func, unsigned int upvalueCount = 0);
|
void PushCFunction(LuaCFunction func, unsigned int upvalueCount = 0);
|
||||||
void PushFunction(LuaFunction func);
|
void PushFunction(LuaFunction func);
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,22 @@ namespace Nz
|
||||||
return static_cast<float>(instance.CheckNumber(index));
|
return static_cast<float>(instance.CheckNumber(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
int LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<int>)
|
template<typename T>
|
||||||
|
std::enable_if_t<std::is_enum<T>::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<T>)
|
||||||
{
|
{
|
||||||
return static_cast<int>(instance.CheckInteger(index));
|
return static_cast<T>(LuaImplQueryArg(instance, index, TypeTag<typename std::underlying_type<T>::type>()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::enable_if_t<std::is_integral<T>::value && !std::is_unsigned<T>::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<T>)
|
||||||
|
{
|
||||||
|
return static_cast<T>(instance.CheckInteger(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::enable_if_t<std::is_unsigned<T>::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<T>)
|
||||||
|
{
|
||||||
|
return static_cast<T>(LuaImplQueryArg(instance, index, TypeTag<typename std::make_signed<T>::type>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<std::string>)
|
std::string LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<std::string>)
|
||||||
|
|
@ -50,51 +63,62 @@ namespace Nz
|
||||||
return LuaImplQueryArg(instance, index, TypeTag<T>());
|
return LuaImplQueryArg(instance, index, TypeTag<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
std::enable_if_t<std::is_unsigned<T>::value, T> LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag<T>)
|
|
||||||
{
|
|
||||||
return static_cast<T>(LuaImplQueryArg(instance, index, TypeTag<typename std::make_signed<T>::type>()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Function returns
|
// Function returns
|
||||||
int LuaImplReplyVal(LuaInstance& instance, bool&& val, TypeTag<bool>)
|
int LuaImplReplyVal(LuaInstance& instance, bool val, TypeTag<bool>)
|
||||||
{
|
{
|
||||||
instance.PushBoolean(val);
|
instance.PushBoolean(val);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LuaImplReplyVal(LuaInstance& instance, double&& val, TypeTag<double>)
|
int LuaImplReplyVal(LuaInstance& instance, double val, TypeTag<double>)
|
||||||
{
|
{
|
||||||
instance.PushNumber(val);
|
instance.PushNumber(val);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LuaImplReplyVal(LuaInstance& instance, float&& val, TypeTag<float>)
|
int LuaImplReplyVal(LuaInstance& instance, float val, TypeTag<float>)
|
||||||
{
|
{
|
||||||
instance.PushNumber(val);
|
instance.PushNumber(val);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LuaImplReplyVal(LuaInstance& instance, int&& val, TypeTag<int>)
|
template<typename T>
|
||||||
|
std::enable_if_t<std::is_enum<T>::value, int> LuaImplReplyVal(LuaInstance& instance, T val, TypeTag<T>)
|
||||||
|
{
|
||||||
|
using EnumT = typename std::underlying_type<T>::type;
|
||||||
|
|
||||||
|
return LuaImplReplyVal(instance, static_cast<EnumT>(val), TypeTag<EnumT>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::enable_if_t<std::is_integral<T>::value && !std::is_unsigned<T>::value, int> LuaImplReplyVal(LuaInstance& instance, T val, TypeTag<T>)
|
||||||
{
|
{
|
||||||
instance.PushInteger(val);
|
instance.PushInteger(val);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LuaImplReplyVal(LuaInstance& instance, std::string&& val, TypeTag<std::string>)
|
template<typename T>
|
||||||
|
std::enable_if_t<std::is_unsigned<T>::value, int> LuaImplReplyVal(LuaInstance& instance, T val, TypeTag<T>)
|
||||||
|
{
|
||||||
|
using SignedT = typename std::make_signed<T>::type;
|
||||||
|
|
||||||
|
return LuaImplReplyVal(instance, static_cast<SignedT>(val), TypeTag<SignedT>());
|
||||||
|
}
|
||||||
|
|
||||||
|
int LuaImplReplyVal(LuaInstance& instance, std::string val, TypeTag<std::string>)
|
||||||
{
|
{
|
||||||
instance.PushString(val.c_str(), val.size());
|
instance.PushString(val.c_str(), val.size());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int LuaImplReplyVal(LuaInstance& instance, String&& val, TypeTag<String>)
|
int LuaImplReplyVal(LuaInstance& instance, String val, TypeTag<String>)
|
||||||
{
|
{
|
||||||
instance.PushString(std::move(val));
|
instance.PushString(std::move(val));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
int LuaImplReplyVal(LuaInstance& instance, std::pair<T1, T2>&& val, TypeTag<std::pair<T1, T2>>)
|
int LuaImplReplyVal(LuaInstance& instance, std::pair<T1, T2> val, TypeTag<std::pair<T1, T2>>)
|
||||||
{
|
{
|
||||||
int retVal = 0;
|
int retVal = 0;
|
||||||
|
|
||||||
|
|
@ -104,14 +128,6 @@ namespace Nz
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
std::enable_if_t<std::is_unsigned<T>::value, int> LuaImplReplyVal(LuaInstance& instance, T&& val, TypeTag<T>)
|
|
||||||
{
|
|
||||||
using SignedT = typename std::make_signed<T>::type;
|
|
||||||
|
|
||||||
return LuaImplReplyVal(instance, val, TypeTag<SignedT>());
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
class LuaImplFunctionProxy
|
class LuaImplFunctionProxy
|
||||||
{
|
{
|
||||||
|
|
@ -152,10 +168,87 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LuaInstance& m_instance;
|
|
||||||
std::tuple<Args...> m_args;
|
std::tuple<Args...> m_args;
|
||||||
|
LuaInstance& m_instance;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T, typename... Args>
|
||||||
|
class LuaImplMethodProxy
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LuaImplMethodProxy(LuaInstance& instance, T& object) :
|
||||||
|
m_instance(instance),
|
||||||
|
m_object(object)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned int N>
|
||||||
|
void ProcessArgs()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned int N, typename ArgType>
|
||||||
|
void ProcessArgs()
|
||||||
|
{
|
||||||
|
std::get<N>(m_args) = std::move(LuaImplQueryArg(m_instance, N + 1, TypeTag<ArgType>()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned int N, typename ArgType1, typename ArgType2, typename... Rest>
|
||||||
|
void ProcessArgs()
|
||||||
|
{
|
||||||
|
ProcessArgs<N, ArgType1>();
|
||||||
|
ProcessArgs<N + 1, ArgType2, Rest...>();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessArgs()
|
||||||
|
{
|
||||||
|
ProcessArgs<0, Args...>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename P>
|
||||||
|
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(void(P::*func)(Args...))
|
||||||
|
{
|
||||||
|
Apply(m_object, func, m_args);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename P, typename Ret>
|
||||||
|
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(Ret(P::*func)(Args...))
|
||||||
|
{
|
||||||
|
return LuaImplReplyVal(m_instance, std::move(Apply(m_object, func, m_args)), TypeTag<decltype(Apply(m_object, func, m_args))>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename P>
|
||||||
|
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(void(P::*func)(Args...) const)
|
||||||
|
{
|
||||||
|
Apply(m_object, func, m_args);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename P, typename Ret>
|
||||||
|
std::enable_if_t<std::is_base_of<P, T>::value, int> Invoke(Ret(P::*func)(Args...) const)
|
||||||
|
{
|
||||||
|
return LuaImplReplyVal(m_instance, std::move(Apply(m_object, func, m_args)), TypeTag<decltype(Apply(m_object, func, m_args))>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::tuple<Args...> m_args;
|
||||||
|
LuaInstance& m_instance;
|
||||||
|
T& m_object;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T LuaInstance::Check(int index)
|
||||||
|
{
|
||||||
|
return LuaImplQueryArg(*this, index, TypeTag<T>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
int LuaInstance::Push(T arg)
|
||||||
|
{
|
||||||
|
return LuaImplReplyVal(*this, std::move(arg), TypeTag<T>());
|
||||||
|
}
|
||||||
|
|
||||||
template<typename R, typename... Args>
|
template<typename R, typename... Args>
|
||||||
void LuaInstance::PushFunction(R (*func)(Args...))
|
void LuaInstance::PushFunction(R (*func)(Args...))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue