/
d.vision
/
division_engine_cpp
Обзор
Документация
Войти
/
d.vision
/
division_engine_cpp
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
include/division_engine/lua/state.hpp
166 строк
4 KB
den163
Improved function generation. Added generic function with lua state
03 июн 2024, 15:49
03 июн 2024, 15:49
5cd4764
Код
Авторство
О чём код?
#pragma once #include <lua.hpp> #include <concepts> #include <string> #include <type_traits> namespace division_engine::lua { template<typename T> concept SupportedLuaType = std::floating_point<T> || std::same_as<T, bool> || std::convertible_to<T, long> || std::same_as<T, void*> || std::convertible_to<T, std::string> || std::same_as<T, lua_CFunction> || std::is_void<T>(); class State { public: State(lua_State* c_state) : _state(c_state) { } lua_State* c_state() { return _state; } template<typename TValue> TValue* get_global_ptr(const std::string& name) { return static_cast<TValue*>(get_global<void*>(name)); } template<typename TValue> void set_global_ptr(const std::string& name, TValue* ptr) { set_global(name, static_cast<void*>(ptr)); } template<SupportedLuaType TValue> TValue get_global(const std::string& name) { lua_getglobal(_state, name.c_str()); return pop_value<TValue>(_state); } template<SupportedLuaType TValue> void set_global(const std::string& name, TValue value) { push_value(_state, value); lua_setglobal(_state, name.c_str()); } void set_global_func(const std::string& name, lua_CFunction func_ptr) { set_global(name, func_ptr); } template<auto Func> void set_generated_global_func(const std::string& name) { using func_t = decltype(Func); using signature_t = lua_function_signature<func_t>; lua_CFunction ptr = signature_t::template function_pointer<Func>; set_global(name, ptr); } private: lua_State* _state; template<typename T> struct lua_function_signature; template<SupportedLuaType TReturn, SupportedLuaType... TArgs> struct lua_function_signature<TReturn (*)(TArgs...)> { using function_type = TReturn(TArgs...); template<function_type Func> static int function_pointer(lua_State* state) { if constexpr (!std::is_same<TReturn, void>()) { push_value(state, Func(pop_value<TArgs>(state)...)); return 1; } else { Func(pop_value<TArgs>(state)...); return 0; } } }; template<SupportedLuaType TReturn> static inline TReturn pop_value(lua_State* state) { const auto& val = peek_value<TReturn>(state); pop(state); return val; } template<SupportedLuaType TReturn> static inline TReturn peek_value(lua_State* state) { if constexpr (std::floating_point<TReturn>) { return static_cast<TReturn>(lua_tonumber(state, -1)); } else if constexpr (std::same_as<TReturn, bool>) { return lua_toboolean(state, -1); } else if constexpr (std::same_as<TReturn, void*>) { return lua_touserdata(state, -1); } else if constexpr (std::convertible_to<TReturn, long>) { return static_cast<TReturn>(lua_tointeger(state, -1)); } else if constexpr (std::convertible_to<TReturn, std::string>) { size_t len = 0; const char* str = lua_tolstring(state, -1, &len); return static_cast<TReturn>(std::string(str, len)); } else if constexpr (std::same_as<TReturn, lua_CFunction>) { return lua_tocfunction(state, -1); } } template<SupportedLuaType TVal> static inline void push_value(lua_State* state, TVal value) { if constexpr (std::floating_point<TVal>) { lua_pushnumber(state, static_cast<double>(value)); } else if constexpr (std::same_as<TVal, bool>) { lua_pushbool(state, value); } else if constexpr (std::same_as<TVal, void*>) { lua_pushlightuserdata(state, value); } else if constexpr (std::convertible_to<TVal, long>) { lua_pushinteger(state, static_cast<long>(value)); } else if constexpr (std::convertible_to<TVal, std::string>) { const auto& str = static_cast<const std::string&>(value); lua_pushlstring(state, str.c_str(), str.size()); } else if constexpr (std::same_as<TVal, lua_CFunction>) { lua_pushcfunction(state, value); } } static inline void pop(lua_State* state) { lua_remove(state, -1); } }; }