Lua/LuaClass: Add possibility to set up a custom converter

Former-commit-id: 96cf62a16845b5cf44d5724bfd3b9e5b7672ad03
This commit is contained in:
Lynix 2016-03-30 18:16:05 +02:00
parent b6ea30f9c1
commit b331d66c70
2 changed files with 33 additions and 16 deletions

View File

@ -29,14 +29,15 @@ namespace Nz
using ClassFunc = std::function<int(LuaInstance& lua, T& instance)>;
using ClassIndexFunc = std::function<bool(LuaInstance& lua, T& instance)>;
using ConstructorFunc = std::function<T*(LuaInstance& lua)>;
template<typename P> using ConvertToParent = std::function<P*(T*)>;
using FinalizerFunc = std::function<bool(LuaInstance& lua, T& instance)>;
using StaticIndexFunc = std::function<bool(LuaInstance& lua)>;
using StaticFunc = std::function<int(LuaInstance& lua)>;
LuaClass(const String& name);
template<class P>
void Inherit(LuaClass<P>& parent);
template<class P> void Inherit(LuaClass<P>& parent);
template<class P> void Inherit(LuaClass<P>& parent, ConvertToParent<P> convertFunc);
void Register(LuaInstance& lua);
@ -57,7 +58,7 @@ namespace Nz
void SetStaticSetter(StaticIndexFunc getter);
private:
using ParentFunc = std::function<void(LuaInstance& lua, T& instance)>;
using ParentFunc = std::function<void(LuaInstance& lua, T* instance)>;
using InstanceGetter = std::function<T*(LuaInstance& lua)>;
struct ClassInfo
@ -79,7 +80,7 @@ namespace Nz
static int ConstructorProxy(lua_State* state);
static int FinalizerProxy(lua_State* state);
static int InfoDestructor(lua_State* state);
static void Get(const std::shared_ptr<ClassInfo>& info, LuaInstance& lua, T& instance);
static void Get(const std::shared_ptr<ClassInfo>& info, LuaInstance& lua, T* instance);
static int GetterProxy(lua_State* state);
static int MethodProxy(lua_State* state);
static int SetterProxy(lua_State* state);

View File

@ -19,19 +19,29 @@ namespace Nz
template<class T>
template<class P>
inline void LuaClass<T>::Inherit(LuaClass<P>& parent)
{
Inherit<P>(parent, [] (T* instance) -> P*
{
return static_cast<P*>(instance);
});
}
template<class T>
template<class P>
inline void LuaClass<T>::Inherit(LuaClass<P>& parent, ConvertToParent<P> convertFunc)
{
static_assert(!std::is_same<P, T>::value || std::is_base_of<P, T>::value, "P must be a base of T");
std::shared_ptr<typename LuaClass<P>::ClassInfo>& parentInfo = parent.m_info;
parentInfo->instanceGetters[m_info->name] = [info = m_info](LuaInstance& lua) -> P*
parentInfo->instanceGetters[m_info->name] = [info = m_info, convertFunc] (LuaInstance& lua) -> P*
{
return *static_cast<T**>(lua.CheckUserdata(1, info->name));
return convertFunc(*static_cast<T**>(lua.CheckUserdata(1, info->name)));
};
m_info->parentGetters.emplace_back([parentInfo] (LuaInstance& lua, T& instance)
m_info->parentGetters.emplace_back([parentInfo, convertFunc] (LuaInstance& lua, T* instance)
{
LuaClass<P>::Get(parentInfo, lua, instance);
LuaClass<P>::Get(parentInfo, lua, convertFunc(instance));
});
}
@ -112,7 +122,7 @@ namespace Nz
lua.SetField(pair.first); // Method name
}
m_info->instanceGetters[m_info->name] = [info = m_info](LuaInstance& lua)
m_info->instanceGetters[m_info->name] = [info = m_info] (LuaInstance& lua)
{
return *static_cast<T**>(lua.CheckUserdata(1, info->name));
};
@ -242,7 +252,7 @@ namespace Nz
{
typename LuaImplMethodProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
SetMethod(name, [func, handler](LuaInstance& lua, T& object) -> int
SetMethod(name, [func, handler] (LuaInstance& lua, T& object) -> int
{
handler.ProcessArgs(lua);
@ -256,7 +266,7 @@ namespace Nz
{
typename LuaImplMethodProxy<Args...>::template Impl<DefArgs...> handler(std::forward<DefArgs>(defArgs)...);
SetMethod(name, [func, handler](LuaInstance& lua, T& object) -> int
SetMethod(name, [func, handler] (LuaInstance& lua, T& object) -> int
{
handler.ProcessArgs(lua);
@ -355,11 +365,11 @@ namespace Nz
}
template<class T>
void LuaClass<T>::Get(const std::shared_ptr<ClassInfo>& info, LuaInstance& lua, T& instance)
void LuaClass<T>::Get(const std::shared_ptr<ClassInfo>& info, LuaInstance& lua, T* instance)
{
const ClassIndexFunc& getter = info->getter;
if (!getter || !getter(lua, instance))
if (!getter || !getter(lua, *instance))
{
// Query from the metatable
lua.GetMetatable(info->name); //< Metatable
@ -389,7 +399,7 @@ namespace Nz
std::shared_ptr<ClassInfo>& info = *static_cast<std::shared_ptr<ClassInfo>*>(lua.ToUserdata(lua.GetIndexOfUpValue(1)));
T& instance = *(*static_cast<T**>(lua.CheckUserdata(1, info->name)));
T* instance = *static_cast<T**>(lua.CheckUserdata(1, info->name));
lua.Remove(1); //< Remove the instance from the Lua stack
Get(info, lua, instance);
@ -415,9 +425,15 @@ namespace Nz
instance = it->second(lua);
}
lua.Pop(2);
lua.Remove(1); //< Remove the instance from the Lua stack
}
lua.Remove(1); //< Remove the instance from the Lua stack
if (!instance)
{
lua.Error("Method cannot be called without an object");
return 0;
}
unsigned int index = static_cast<unsigned int>(lua.ToInteger(lua.GetIndexOfUpValue(2)));
const ClassFunc& method = info->methods[index];