Lua: Add automatic function binding

Former-commit-id: dcb1d3ca474c9e10f9a40428095a5ff752f5c4a9
This commit is contained in:
Lynix 2015-09-10 18:03:52 +02:00
parent 505f1dbb03
commit 73e03073eb
5 changed files with 177 additions and 4 deletions

View File

@ -14,6 +14,9 @@
template<typename F, typename Tuple> auto NzApply(F&& fn, Tuple&& t);
template<typename T> void NzHashCombine(std::size_t& seed, const T& v);
template<typename T>
struct NzTypeTag {};
#include <Nazara/Core/Algorithm.inl>
#endif // NAZARA_ALGORITHM_CORE_HPP

View File

@ -108,8 +108,9 @@ class NAZARA_LUA_API NzLuaInstance : NzNonCopyable
void Pop(unsigned int n = 1U);
void PushBoolean(bool value);
void PushCFunction(NzLuaCFunction func, int upvalueCount = 0);
void PushCFunction(NzLuaCFunction func, unsigned int upvalueCount = 0);
void PushFunction(NzLuaFunction func);
template<typename R, typename... Args> void PushFunction(R(*func)(Args...));
void PushInteger(long long value);
void PushLightUserdata(void* value);
void PushMetatable(const char* str);
@ -118,6 +119,7 @@ class NAZARA_LUA_API NzLuaInstance : NzNonCopyable
void PushNumber(double value);
void PushReference(int ref);
void PushString(const char* str);
void PushString(const char* str, unsigned int size);
void PushString(const NzString& str);
void PushTable(unsigned int sequenceElementCount = 0, unsigned int arrayElementCount = 0);
void* PushUserdata(unsigned int size);
@ -165,4 +167,6 @@ class NAZARA_LUA_API NzLuaInstance : NzNonCopyable
unsigned int m_level;
};
#include <Nazara/Lua/LuaInstance.inl>
#endif // NAZARA_LUASTATE_HPP

View File

@ -0,0 +1,161 @@
// Copyright (C) 2015 Jérôme Leclercq
// This file is part of the "Nazara Engine - Lua scripting module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Core/Algorithm.hpp>
#include <string>
// Functions args
bool NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<bool>)
{
return instance.CheckBoolean(index);
}
double NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<double>)
{
return instance.CheckNumber(index);
}
float NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<float>)
{
return instance.CheckNumber(index);
}
int NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<int>)
{
return instance.CheckInteger(index);
}
std::string NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<std::string>)
{
return instance.CheckString(index);
}
NzString NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<NzString>)
{
return instance.CheckString(index);
}
template<typename T>
T NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<const T&>)
{
return NzLuaImplQueryArg(instance, index, NzTypeTag<T>());
}
template<typename T>
std::enable_if_t<std::is_unsigned<T>::value, T> NzLuaImplQueryArg(NzLuaInstance& instance, unsigned int index, NzTypeTag<T>)
{
return static_cast<T>(NzLuaImplQueryArg(instance, index, NzTypeTag<typename std::make_signed<T>::type>()));
}
// Function returns
int NzLuaImplReplyVal(NzLuaInstance& instance, bool&& val, NzTypeTag<bool>)
{
instance.PushBoolean(val);
return 1;
}
int NzLuaImplReplyVal(NzLuaInstance& instance, double&& val, NzTypeTag<double>)
{
instance.PushNumber(val);
return 1;
}
int NzLuaImplReplyVal(NzLuaInstance& instance, float&& val, NzTypeTag<float>)
{
instance.PushNumber(val);
return 1;
}
int NzLuaImplReplyVal(NzLuaInstance& instance, int&& val, NzTypeTag<int>)
{
instance.PushInteger(val);
return 1;
}
int NzLuaImplReplyVal(NzLuaInstance& instance, std::string&& val, NzTypeTag<std::string>)
{
instance.PushString(val.c_str(), val.size());
return 1;
}
int NzLuaImplReplyVal(NzLuaInstance& instance, NzString&& val, NzTypeTag<NzString>)
{
instance.PushString(std::move(val));
return 1;
}
template<typename T1, typename T2>
int NzLuaImplReplyVal(NzLuaInstance& instance, std::pair<T1, T2>&& val, NzTypeTag<std::pair<T1, T2>>)
{
int retVal = 0;
retVal += NzLuaImplReplyVal(instance, std::move(val.first), NzTypeTag<T1>());
retVal += NzLuaImplReplyVal(instance, std::move(val.second), NzTypeTag<T2>());
return retVal;
}
template<typename T>
std::enable_if_t<std::is_unsigned<T>::value, int> NzLuaImplReplyVal(NzLuaInstance& instance, T&& val, NzTypeTag<T>)
{
using SignedT = typename std::make_signed<T>::type;
return NzLuaImplReplyVal(instance, val, NzTypeTag<SignedT>());
}
template<typename... Args>
class NzLuaImplFunctionProxy
{
public:
NzLuaImplFunctionProxy(NzLuaInstance& instance) :
m_instance(instance)
{
}
template<unsigned int N, typename ArgType>
void ProcessArgs()
{
std::get<N>(m_args) = std::move(NzLuaImplQueryArg(m_instance, N+1, NzTypeTag<ArgType>()));
}
template<int N, typename ArgType1, typename ArgType2, typename... Rest>
void ProcessArgs()
{
ProcessArgs<N, ArgType1>();
ProcessArgs<N+1, ArgType2, Rest...>();
}
void ProcessArgs()
{
ProcessArgs<0, Args...>();
}
int Invoke(void (*func)(Args...))
{
NzApply(func, m_args);
return 0;
}
template<typename Ret>
int Invoke(Ret (*func)(Args...))
{
return NzLuaImplReplyVal(m_instance, std::move(NzApply(func, m_args)), NzTypeTag<decltype(NzApply(func, m_args))>());
}
private:
NzLuaInstance& m_instance;
std::tuple<Args...> m_args;
};
template<typename R, typename... Args>
void NzLuaInstance::PushFunction(R(*func)(Args...))
{
PushFunction([func](NzLuaInstance& instance) -> int
{
NzLuaImplFunctionProxy<Args...> handler(instance);
handler.ProcessArgs();
return handler.Invoke(func);
});
}

View File

@ -121,7 +121,7 @@
#define NAZARA_EXPORT __attribute__((visibility ("default")))
#define NAZARA_IMPORT __attribute__((visibility ("default")))
/*#elif defined(__APPLE__) && defined(__MACH__)
#define NAZARA_API
#define NAZARA_CORE_API
#define NAZARA_PLATFORM_MACOSX
#define NAZARA_PLATFORM_POSIX*/
#else
@ -129,7 +129,7 @@
#error This operating system is not fully supported by the Nazara Engine
#define NAZARA_PLATFORM_UNKNOWN
#define NAZARA_API
#define NAZARA_CORE_API
#endif
// Détection 64 bits

View File

@ -624,7 +624,7 @@ void NzLuaInstance::PushBoolean(bool value)
lua_pushboolean(m_state, (value) ? 1 : 0);
}
void NzLuaInstance::PushCFunction(NzLuaCFunction func, int upvalueCount)
void NzLuaInstance::PushCFunction(NzLuaCFunction func, unsigned int upvalueCount)
{
lua_pushcclosure(m_state, func, upvalueCount);
}
@ -677,6 +677,11 @@ void NzLuaInstance::PushString(const char* str)
lua_pushstring(m_state, str);
}
void NzLuaInstance::PushString(const char* str, unsigned int size)
{
lua_pushlstring(m_state, str, size);
}
void NzLuaInstance::PushString(const NzString& str)
{
lua_pushlstring(m_state, str.GetConstBuffer(), str.GetSize());