// 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 #include namespace Nz { // Functions args bool LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { return instance.CheckBoolean(index); } double LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { return instance.CheckNumber(index); } float LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { return static_cast(instance.CheckNumber(index)); } int LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { return static_cast(instance.CheckInteger(index)); } std::string LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { std::size_t strLength = 0; const char* str = instance.CheckString(index, &strLength); return std::string(str, strLength); } String LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { std::size_t strLength = 0; const char* str = instance.CheckString(index, &strLength); return String(str, strLength); } template T LuaImplQueryArg(LuaInstance& instance, unsigned int index, TypeTag) { 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) { instance.PushBoolean(val); return 1; } int LuaImplReplyVal(LuaInstance& instance, double&& val, TypeTag) { instance.PushNumber(val); return 1; } int LuaImplReplyVal(LuaInstance& instance, float&& val, TypeTag) { instance.PushNumber(val); return 1; } int LuaImplReplyVal(LuaInstance& instance, int&& val, TypeTag) { instance.PushInteger(val); return 1; } int LuaImplReplyVal(LuaInstance& instance, std::string&& val, TypeTag) { instance.PushString(val.c_str(), val.size()); return 1; } int LuaImplReplyVal(LuaInstance& instance, String&& val, TypeTag) { instance.PushString(std::move(val)); return 1; } template int LuaImplReplyVal(LuaInstance& instance, std::pair&& val, TypeTag>) { int retVal = 0; retVal += LuaImplReplyVal(instance, std::move(val.first), TypeTag()); retVal += LuaImplReplyVal(instance, std::move(val.second), TypeTag()); 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 { public: LuaImplFunctionProxy(LuaInstance& instance) : m_instance(instance) { } 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...>(); } int Invoke(void (*func)(Args...)) { Apply(func, m_args); return 0; } template int Invoke(Ret (*func)(Args...)) { return LuaImplReplyVal(m_instance, std::move(Apply(func, m_args)), TypeTag()); } private: LuaInstance& m_instance; std::tuple m_args; }; template void LuaInstance::PushFunction(R(*func)(Args...)) { PushFunction([func](LuaInstance& instance) -> int { LuaImplFunctionProxy handler(instance); handler.ProcessArgs(); return handler.Invoke(func); }); } }