Merge pull request #662 from HotaruBlaze/cleanup-lua-templates

Cleanup(server): Refactor code for Lua function dispatch
master
David Cernat 1 year ago committed by GitHub
commit 00997fa732
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -53,53 +53,67 @@ LangLua::~LangLua()
} }
template<unsigned int I, unsigned int F> // LuaFunctionDispatcher template struct for Lua function dispatch
struct Lua_dispatch_ { template <unsigned int ArgIndex, unsigned int FunctionIndex>
template<typename R, typename... Args> struct LuaFunctionDispatcher {
inline static R Lua_dispatch(lua_State*&& lua, Args&&... args) noexcept { // Dispatch Lua function with the given arguments
constexpr ScriptFunctionData const& F_ = ScriptFunctions::functions[F]; template <typename ReturnType, typename... Args>
auto arg = luabridge::Stack<typename CharType<F_.func.types[I - 1]>::type>::get(lua, I); inline static ReturnType Dispatch(lua_State*&& lua, Args&&... args) noexcept {
return Lua_dispatch_<I - 1, F>::template Lua_dispatch<R>( // Retrieve function data
std::forward<lua_State*>(lua), constexpr ScriptFunctionData const& functionData = ScriptFunctions::functions[FunctionIndex];
arg, // Retrieve argument from the Lua stack
std::forward<Args>(args)...); auto argument = luabridge::Stack<typename CharType<functionData.func.types[ArgIndex - 1]>::type>::get(lua, ArgIndex);
// Recursively dispatch the Lua function
return LuaFunctionDispatcher<ArgIndex - 1, FunctionIndex>::template Dispatch<ReturnType>(
std::forward<lua_State*>(lua), argument, std::forward<Args>(args)...);
} }
}; };
template<unsigned int F> // Specialization for LuaFunctionDispatcher when ArgIndex is 0
struct Lua_dispatch_<0, F> { template <unsigned int FunctionIndex>
template<typename R, typename... Args> struct LuaFunctionDispatcher<0, FunctionIndex> {
inline static R Lua_dispatch(lua_State*&&, Args&&... args) noexcept { // Dispatch Lua function with the given arguments
constexpr ScriptFunctionData const& F_ = ScriptFunctions::functions[F]; template <typename ReturnType, typename... Args>
return reinterpret_cast<FunctionEllipsis<R>>(F_.func.addr)(std::forward<Args>(args)...); inline static ReturnType Dispatch(lua_State*&&, Args&&... args) noexcept {
// Retrieve function data
constexpr ScriptFunctionData const& functionData = ScriptFunctions::functions[FunctionIndex];
// Call the C++ function using reinterpret_cast
return reinterpret_cast<FunctionEllipsis<ReturnType>>(functionData.func.addr)(std::forward<Args>(args)...);
} }
}; };
template<unsigned int I> // Lua function wrapper for functions returning 'void'
static typename std::enable_if<ScriptFunctions::functions[I].func.ret == 'v', int>::type wrapper(lua_State* lua) noexcept { template <unsigned int FunctionIndex>
Lua_dispatch_<ScriptFunctions::functions[I].func.numargs, I>::template Lua_dispatch<void>(std::forward<lua_State*>(lua)); static typename std::enable_if<ScriptFunctions::functions[FunctionIndex].func.ret == 'v', int>::type LuaFunctionWrapper(lua_State* lua) noexcept {
// Dispatch the Lua function
LuaFunctionDispatcher<ScriptFunctions::functions[FunctionIndex].func.numargs, FunctionIndex>::template Dispatch<void>(std::forward<lua_State*>(lua));
return 0; return 0;
} }
template<unsigned int I> // Lua function wrapper for functions with non-void return types
static typename std::enable_if<ScriptFunctions::functions[I].func.ret != 'v', int>::type wrapper(lua_State* lua) noexcept { template <unsigned int FunctionIndex>
auto ret = Lua_dispatch_<ScriptFunctions::functions[I].func.numargs, I>::template Lua_dispatch< static typename std::enable_if<ScriptFunctions::functions[FunctionIndex].func.ret != 'v', int>::type LuaFunctionWrapper(lua_State* lua) noexcept {
typename CharType<ScriptFunctions::functions[I].func.ret>::type>(std::forward<lua_State*>(lua)); // Dispatch the Lua function
luabridge::Stack <typename CharType<ScriptFunctions::functions[I].func.ret>::type>::push (lua, ret); auto result = LuaFunctionDispatcher<ScriptFunctions::functions[FunctionIndex].func.numargs, FunctionIndex>::template Dispatch<
typename CharType<ScriptFunctions::functions[FunctionIndex].func.ret>::type>(std::forward<lua_State*>(lua));
// Push the result onto the Lua stack
luabridge::Stack<typename CharType<ScriptFunctions::functions[FunctionIndex].func.ret>::type>::push(lua, result);
return 1; return 1;
} }
template<unsigned int I> // Struct for defining Lua functions with names and wrappers
struct F_ template <unsigned int FunctionIndex>
{ struct LuaFunctionDefinition {
static constexpr LuaFuctionData F{ScriptFunctions::functions[I].name, wrapper<I>}; static constexpr LuaFunctionData FunctionInfo{
ScriptFunctions::functions[FunctionIndex].name, LuaFunctionWrapper<FunctionIndex>
};
}; };
template<> struct LuaFunctionDefinition<0> { static constexpr LuaFunctionData FunctionInfo{"CreateTimer", LangLua::CreateTimer}; };
template<> struct LuaFunctionDefinition<1> { static constexpr LuaFunctionData FunctionInfo{"CreateTimerEx", LangLua::CreateTimerEx}; };
template<> struct LuaFunctionDefinition<2> { static constexpr LuaFunctionData FunctionInfo{"MakePublic", LangLua::MakePublic}; };
template<> struct LuaFunctionDefinition<3> { static constexpr LuaFunctionData FunctionInfo{"CallPublic", LangLua::CallPublic}; };
template<> struct F_<0> { static constexpr LuaFuctionData F{"CreateTimer", LangLua::CreateTimer}; };
template<> struct F_<1> { static constexpr LuaFuctionData F{"CreateTimerEx", LangLua::CreateTimerEx}; };
template<> struct F_<2> { static constexpr LuaFuctionData F{"MakePublic", LangLua::MakePublic}; };
template<> struct F_<3> { static constexpr LuaFuctionData F{"CallPublic", LangLua::CallPublic}; };
#ifdef __arm__ #ifdef __arm__
template<std::size_t... Is> template<std::size_t... Is>
@ -128,30 +142,29 @@ LuaFuctionData *functions(indices<Indices...>)
} }
#else #else
template<unsigned int I> template<unsigned int I>
struct C struct LuaFunctionInitializer
{ {
constexpr static void Fn(LuaFuctionData *functions_) constexpr static void Initialize(LuaFunctionData *functions_)
{ {
functions_[I] = F_<I>::F; functions_[I] = LuaFunctionDefinition<I>::FunctionInfo;
C<I - 1>::Fn(functions_); LuaFunctionInitializer<I - 1>::Initialize(functions_);
} }
}; };
template<> template<>
struct C<0> struct LuaFunctionInitializer<0>
{ {
constexpr static void Fn(LuaFuctionData *functions_) constexpr static void Initialize(LuaFunctionData *functions_)
{ {
functions_[0] = F_<0>::F; functions_[0] = LuaFunctionDefinition<0>::FunctionInfo;
} }
}; };
template<size_t LastI> template<size_t LastI>
LuaFuctionData *functions() LuaFunctionData *GetLuaFunctions()
{ {
static LuaFunctionData functions_[LastI];
static LuaFuctionData functions_[LastI]; LuaFunctionInitializer<LastI - 1>::Initialize(functions_);
C<LastI - 1>::Fn(functions_);
static_assert( static_assert(
sizeof(functions_) / sizeof(functions_[0]) == sizeof(functions_) / sizeof(functions_[0]) ==
@ -173,20 +186,21 @@ void LangLua::LoadProgram(const char *filename)
constexpr auto functions_n = sizeof(ScriptFunctions::functions) / sizeof(ScriptFunctions::functions[0]); constexpr auto functions_n = sizeof(ScriptFunctions::functions) / sizeof(ScriptFunctions::functions[0]);
#ifdef __arm__ #ifdef __arm__
LuaFuctionData *functions_ = functions(IndicesFor<functions_n>{}); LuaFunctionData *functions_ = GetLuaFunctions(IndicesFor<functions_n>{});
#else #else
LuaFuctionData *functions_ = functions<sizeof(ScriptFunctions::functions) / sizeof(ScriptFunctions::functions[0])>(); LuaFunctionData *functions_ = GetLuaFunctions<sizeof(ScriptFunctions::functions) / sizeof(ScriptFunctions::functions[0])>();
#endif #endif
luabridge::Namespace tes3mp = luabridge::getGlobalNamespace(lua).beginNamespace("tes3mp"); luabridge::Namespace tes3mp = luabridge::getGlobalNamespace(lua).beginNamespace("tes3mp");
for (unsigned i = 0; i < functions_n; i++) for (unsigned i = 0; i < functions_n; i++)
tes3mp.addCFunction(functions_[i].name, functions_[i].func); tes3mp.addCFunction(functions_[i].name, functions_[i].func);
tes3mp.endNamespace(); tes3mp.endNamespace();
if ((err = lua_pcall(lua, 0, 0, 0)) != 0) // Run once script for load in memory.
throw std::runtime_error("Lua script " + std::string(filename) + " error (" + std::to_string(err) + "): \"" +
std::string(lua_tostring(lua, -1)) + "\"");
if ((err = lua_pcall(lua, 0, 0, 0)) != 0) // Run once script for load in memory.
throw std::runtime_error("Lua script " + std::string(filename) + " error (" + std::to_string(err) + "): \"" +
std::string(lua_tostring(lua, -1)) + "\"");
} }
int LangLua::FreeProgram() int LangLua::FreeProgram()

@ -11,7 +11,7 @@
#include "../ScriptFunction.hpp" #include "../ScriptFunction.hpp"
#include "../Language.hpp" #include "../Language.hpp"
struct LuaFuctionData struct LuaFunctionData
{ {
const char* name; const char* name;
lua_CFunction func; lua_CFunction func;

Loading…
Cancel
Save