diff --git a/native/projects/lcpu/CMakeLists.txt b/native/projects/lcpu/CMakeLists.txt index 131bbe7..cafe513 100644 --- a/native/projects/lcpu/CMakeLists.txt +++ b/native/projects/lcpu/CMakeLists.txt @@ -5,7 +5,10 @@ add_library(lcpu_native SHARED src/LcpuGlobals.cpp src/LuaCpu.cpp src/LuaDevice.cpp + + # Support code src/SourceSink.cpp + src/LuaShared.cpp ) if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") diff --git a/native/projects/lcpu/src/LuaShared.cpp b/native/projects/lcpu/src/LuaShared.cpp new file mode 100644 index 0000000..032269b --- /dev/null +++ b/native/projects/lcpu/src/LuaShared.cpp @@ -0,0 +1,38 @@ +#include "LuaShared.hpp" + +#include +#include + +namespace lcpu::lua { + + // A global pointer to the loaded instance of the lua_shared library. + lucore::Library* luaSharedLibrary = nullptr; + +#define LUA_SHARED_FUNC(Retty, name, ...) Retty (*name)(__VA_ARGS__) = nullptr; +#include "LuaSharedFunctions.inc" +#undef LUA_SHARED_FUNC + + void LoadLuaShared() { + // Open the lua_shared library + luaSharedLibrary = lucore::Library::OpenExisting("lua_shared"); + LUCORE_CHECK(luaSharedLibrary != nullptr, "Could not open lua_shared library for some reason."); + + // Load the functions from lua_shared + // This is helped quite a bit by using an x-macro +#define LUA_SHARED_FUNC(Retty, name, ...) \ + name = luaSharedLibrary->Symbol(#name); \ + LUCORE_CHECK(name != nullptr, "Could not load lua_shared function \"{}\"", #name); +#include "LuaSharedFunctions.inc" +#undef LUA_SHARED_FUNC + } + + void UnloadLuaShared() { + LUCORE_ASSERT(luaSharedLibrary != nullptr, "UnloadLuaShared() should only be called if LoadLuaShared() was called"); + delete luaSharedLibrary; + +#define LUA_SHARED_FUNC(Retty, name, ...) name = nullptr; +#include "LuaSharedFunctions.inc" +#undef LUA_SHARED_FUNC + } + +} // namespace lcpu::lua diff --git a/native/projects/lcpu/src/LuaShared.hpp b/native/projects/lcpu/src/LuaShared.hpp new file mode 100644 index 0000000..168ab0e --- /dev/null +++ b/native/projects/lcpu/src/LuaShared.hpp @@ -0,0 +1,56 @@ +//! Loader/types for lua_shared API. I plan to use this instead of the Garry's Mod +//! ILuaBase interface; they are interchangable (and in fact, less friction to use!) + +#pragma once + +#include + +namespace lcpu::lua { + +#define LUA_IDSIZE 60 /* Size of lua_Debug.short_src. */ + + struct lua_Debug { + int event; + const char* name; /* (n) */ + const char* namewhat; /* (n) `global', `local', `field', `method' */ + const char* what; /* (S) `Lua', `C', `main', `tail' */ + const char* source; /* (S) */ + int currentline; /* (l) */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + int i_ci; /* active function */ + }; + + typedef int (*lua_CFunction)(lua_State* L); + typedef void* (*lua_Alloc)(void* ud, void* ptr, size_t osize, size_t nsize); + typedef const char* (*lua_Reader)(lua_State* L, void* ud, size_t* sz); + typedef int (*lua_Writer)(lua_State* L, const void* p, size_t sz, void* ud); + //typedef struct lua_Debug lua_Debug; /* activation record */ + typedef void (*lua_Hook)(lua_State* L, lua_Debug* ar); + + typedef struct luaL_Buffer { + char* p; /* current position in buffer */ + int lvl; /* number of strings in the stack (level) */ + lua_State* L; + char buffer[8192]; + } luaL_Buffer; + + typedef struct luaL_Reg { + const char* name; + lua_CFunction func; + } luaL_Reg; + +#define LUA_SHARED_FUNC(Retty, name, ...) extern Retty (*name)(__VA_ARGS__); + #include "LuaSharedFunctions.inc" +#undef LUA_SHARED_FUNC + + /// Load lua_shared + void LoadLuaShared(); + + /// .. and unload it. + void UnloadLuaShared(); + +} // namespace lcpu::lua diff --git a/native/projects/lcpu/src/LuaSharedFunctions.inc b/native/projects/lcpu/src/LuaSharedFunctions.inc new file mode 100644 index 0000000..f749d9d --- /dev/null +++ b/native/projects/lcpu/src/LuaSharedFunctions.inc @@ -0,0 +1,128 @@ +//! This is an X-Macro file of all the interesting functions in lua_shared +LUA_SHARED_FUNC(lua_State*, luaL_newstate, void); +LUA_SHARED_FUNC(int, luaL_loadstring, lua_State *L, const char* code); +LUA_SHARED_FUNC(lua_CFunction, lua_atpanic, lua_State *L, lua_CFunction panicf); +LUA_SHARED_FUNC(void, lua_call, lua_State *L, int nargs, int nresults); +LUA_SHARED_FUNC(int, lua_checkstack, lua_State *L, int size); +LUA_SHARED_FUNC(void, lua_close, lua_State *L); +LUA_SHARED_FUNC(void, lua_concat, lua_State*L,int n); +LUA_SHARED_FUNC(int, lua_cpcall, lua_State *L, lua_CFunction func, void *ud); +LUA_SHARED_FUNC(void, lua_createtable, lua_State *L, int narray, int nrec); +LUA_SHARED_FUNC(int, lua_dump, lua_State *L, lua_Writer writer, void *data); +LUA_SHARED_FUNC(int, lua_equal, lua_State *L, int idx1, int idx2); +LUA_SHARED_FUNC(int, lua_error, lua_State *L); +LUA_SHARED_FUNC(int, lua_gc, lua_State *L, int what, int data); +LUA_SHARED_FUNC(lua_Alloc, lua_getallocf, lua_State *L, void **ud); +LUA_SHARED_FUNC(void, lua_getfenv, lua_State *L, int idx); +LUA_SHARED_FUNC(void, lua_getfield, lua_State *L, int idx, const char *k); +LUA_SHARED_FUNC(lua_Hook, lua_gethook, lua_State *L); +LUA_SHARED_FUNC(int, lua_gethookcount, lua_State *L); +LUA_SHARED_FUNC(int, lua_gethookmask, lua_State *L); +LUA_SHARED_FUNC(int, lua_getinfo, lua_State *L, const char *what, lua_Debug *ar); +LUA_SHARED_FUNC(const char*, lua_getlocal, lua_State *L, const lua_Debug *ar, int n); +LUA_SHARED_FUNC(int, lua_getmetatable, lua_State *L, int idx); +LUA_SHARED_FUNC(int, lua_getstack, lua_State *L, int level, lua_Debug *ar); +LUA_SHARED_FUNC(void, lua_gettable, lua_State *L, int idx); +LUA_SHARED_FUNC(int, lua_gettop, lua_State *L); +LUA_SHARED_FUNC(const char*, lua_getupvalue, lua_State *L, int idx, int n); +LUA_SHARED_FUNC(void, lua_insert, lua_State *L, int idx); +LUA_SHARED_FUNC(int, lua_iscfunction, lua_State *L, int idx); +LUA_SHARED_FUNC(int, lua_isnumber, lua_State *L, int idx); +LUA_SHARED_FUNC(int, lua_isstring, lua_State *L, int idx); +LUA_SHARED_FUNC(int, lua_isuserdata, lua_State *L, int idx); +LUA_SHARED_FUNC(int, lua_lessthan, lua_State *L, int idx1, int idx2); +LUA_SHARED_FUNC(int, lua_load, lua_State *L, lua_Reader reader, void *dt, const char *chunkname); +LUA_SHARED_FUNC(int, lua_loadx, lua_State *L, lua_Reader reader, void *dt, const char *chunkname, const char *mode); +LUA_SHARED_FUNC(lua_State*, lua_newstate, lua_Alloc f, void *ud); +LUA_SHARED_FUNC(lua_State*, lua_newthread, lua_State *L); +LUA_SHARED_FUNC(void*, lua_newuserdata, lua_State *L, size_t size); +LUA_SHARED_FUNC(int, lua_next, lua_State *L, int idx); +LUA_SHARED_FUNC(size_t, lua_objlen, lua_State *L, int idx); +LUA_SHARED_FUNC(int, lua_pcall, lua_State *L, int nargs, int nresults, int errfunc); +LUA_SHARED_FUNC(void, lua_pushboolean, lua_State *L, int b); +LUA_SHARED_FUNC(void, lua_pushcclosure, lua_State *L, lua_CFunction f, int n); +LUA_SHARED_FUNC(const char*, lua_pushfstring, lua_State *L, const char *fmt, ...); +LUA_SHARED_FUNC(void, lua_pushlightuserdata, lua_State *L, void *p); +LUA_SHARED_FUNC(void, lua_pushlstring, lua_State *L, const char *str, size_t len); +LUA_SHARED_FUNC(void, lua_pushnil, lua_State *L); +LUA_SHARED_FUNC(void, lua_pushnumber, lua_State *L, double n); +LUA_SHARED_FUNC(void, lua_pushstring, lua_State *L, const char *str); +LUA_SHARED_FUNC(int, lua_pushthread, lua_State *L); +LUA_SHARED_FUNC(void, lua_pushvalue, lua_State *L, int idx); +LUA_SHARED_FUNC(const char*, lua_pushvfstring, lua_State *L, const char *fmt, char* argp); +LUA_SHARED_FUNC(int, lua_rawequal, lua_State *L, int idx1, int idx2); +LUA_SHARED_FUNC(void, lua_rawget, lua_State *L, int idx); +LUA_SHARED_FUNC(void, lua_rawgeti, lua_State *L, int idx, int n); +LUA_SHARED_FUNC(void, lua_rawset, lua_State *L, int idx); +LUA_SHARED_FUNC(void, lua_rawseti, lua_State *L, int idx, int n); +LUA_SHARED_FUNC(void, lua_remove, lua_State *L, int idx); +LUA_SHARED_FUNC(void, lua_replace, lua_State *L, int idx); +LUA_SHARED_FUNC(void, lua_setallocf, lua_State *L, lua_Alloc f, void *ud); +LUA_SHARED_FUNC(int, lua_setfenv, lua_State *L, int idx); +LUA_SHARED_FUNC(void, lua_setfield, lua_State *L, int idx, const char *k); +LUA_SHARED_FUNC(int, lua_sethook, lua_State *L, lua_Hook func, int mask, int count); +LUA_SHARED_FUNC(const char *, lua_setlocal, lua_State *L, const lua_Debug *ar, int n); +LUA_SHARED_FUNC(int, lua_setmetatable, lua_State *L, int idx); +LUA_SHARED_FUNC(void, lua_settable, lua_State *L, int idx); +LUA_SHARED_FUNC(void, lua_settop, lua_State *L, int idx); +LUA_SHARED_FUNC(const char*, lua_setupvalue, lua_State *L, int idx, int n); +LUA_SHARED_FUNC(int, lua_status, lua_State *L); +LUA_SHARED_FUNC(int, lua_toboolean, lua_State *L, int idx); +LUA_SHARED_FUNC(lua_CFunction, lua_tocfunction, lua_State *L, int idx); +LUA_SHARED_FUNC(const char*, lua_tolstring, lua_State *L, int idx, size_t *len); +LUA_SHARED_FUNC(double, lua_tonumber, lua_State *L, int idx); +LUA_SHARED_FUNC(const void*, lua_topointer, lua_State *L, int idx); +LUA_SHARED_FUNC(lua_State*, lua_tothread, lua_State *L, int idx); +LUA_SHARED_FUNC(void*, lua_touserdata, lua_State *L, int idx); +LUA_SHARED_FUNC(int, lua_type, lua_State *L, int idx); +LUA_SHARED_FUNC(const char*, lua_typename, lua_State *L, int t); +LUA_SHARED_FUNC(void*, lua_upvalueid, lua_State *L, int idx, int n); +LUA_SHARED_FUNC(void, lua_upvaluejoin, lua_State *L, int idx1, int n1, int idx2, int n2); +LUA_SHARED_FUNC(void, lua_xmove, lua_State *from, lua_State *to, int n); +LUA_SHARED_FUNC(int, lua_yield, lua_State *L, int nresults); +LUA_SHARED_FUNC(int, luaJIT_setmode, lua_State *L, int idx, int mode); +LUA_SHARED_FUNC(void, luaL_addlstring, luaL_Buffer *B, const char *s, size_t l); +LUA_SHARED_FUNC(void, luaL_addstring, luaL_Buffer *B, const char *s); +LUA_SHARED_FUNC(void, luaL_addvalue, luaL_Buffer *B); +LUA_SHARED_FUNC(int, luaL_argerror, lua_State *L, int narg, const char *msg); +LUA_SHARED_FUNC(void, luaL_buffinit, lua_State *L, luaL_Buffer *B); +LUA_SHARED_FUNC(int, luaL_callmeta, lua_State *L, int idx, const char *field); +LUA_SHARED_FUNC(void, luaL_checkany, lua_State *L, int idx); +LUA_SHARED_FUNC(const char*, luaL_checklstring, lua_State *L, int idx, size_t *len); +LUA_SHARED_FUNC(double, luaL_checknumber, lua_State *L, int idx); +LUA_SHARED_FUNC(int, luaL_checkoption, lua_State *L, int idx, const char *def, const char *const lst[]); +LUA_SHARED_FUNC(void, luaL_checkstack, lua_State *L, int size, const char *msg); +LUA_SHARED_FUNC(void, luaL_checktype, lua_State *L, int idx, int tt); +LUA_SHARED_FUNC(void*, luaL_checkudata, lua_State *L, int idx, const char *tname); +LUA_SHARED_FUNC(int, luaL_error, lua_State *L, const char *fmt, ...); +LUA_SHARED_FUNC(int, luaL_execresult, lua_State *L, int stat); +LUA_SHARED_FUNC(int, luaL_fileresult, lua_State *L, int stat, const char *fname); +LUA_SHARED_FUNC(const char*, luaL_findtable, lua_State *L, int idx, const char *fname, int szhint); +LUA_SHARED_FUNC(int, luaL_getmetafield, lua_State *L, int idx, const char *field); +LUA_SHARED_FUNC(const char*, luaL_gsub, lua_State *L, const char *s, const char *p, const char *r); +LUA_SHARED_FUNC(int, luaL_loadbuffer, lua_State *L, const char *buff, size_t sz, const char *name); +LUA_SHARED_FUNC(int, luaL_loadbufferx, lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); +LUA_SHARED_FUNC(int, luaL_loadfile, lua_State *L, const char *filename); +LUA_SHARED_FUNC(int, luaL_loadfilex, lua_State *L, const char *filename, const char *mode); +LUA_SHARED_FUNC(int, luaL_newmetatable, lua_State *L, const char *tname); +LUA_SHARED_FUNC(void, luaL_openlib, lua_State *L, const char *libname, const luaL_Reg *l, int nup); +LUA_SHARED_FUNC(int, luaL_openlibs, lua_State *L); +LUA_SHARED_FUNC(const char*, luaL_optlstring, lua_State *L, int idx, const char *def, size_t *len); +LUA_SHARED_FUNC(double, luaL_optnumber, lua_State *L, int idx, double def); +LUA_SHARED_FUNC(char*, luaL_prepbuffer, luaL_Buffer *B); +LUA_SHARED_FUNC(void, luaL_pushresult, luaL_Buffer *B); +LUA_SHARED_FUNC(int, luaL_ref, lua_State *L, int t); +LUA_SHARED_FUNC(void, luaL_register, lua_State *L, const char *libname, const luaL_Reg *l); +LUA_SHARED_FUNC(void, luaL_traceback, lua_State *L, lua_State *L1, const char *msg, int level); +LUA_SHARED_FUNC(int, luaL_typerror, lua_State *L, int narg, const char *tname); +LUA_SHARED_FUNC(void, luaL_unref, lua_State *L, int t, int ref); +LUA_SHARED_FUNC(void, luaL_where, lua_State *L, int lvl); +LUA_SHARED_FUNC(int, luaopen_base, lua_State *L); +LUA_SHARED_FUNC(int, luaopen_bit, lua_State *L); +LUA_SHARED_FUNC(int, luaopen_debug, lua_State *L); +LUA_SHARED_FUNC(int, luaopen_jit, lua_State *L); +LUA_SHARED_FUNC(int, luaopen_math, lua_State *L); +LUA_SHARED_FUNC(int, luaopen_os, lua_State *L); +LUA_SHARED_FUNC(int, luaopen_package, lua_State *L); +LUA_SHARED_FUNC(int, luaopen_string, lua_State *L); +LUA_SHARED_FUNC(int, luaopen_table, lua_State *L); diff --git a/native/projects/lcpu/src/SourceSink.cpp b/native/projects/lcpu/src/SourceSink.cpp index 9254290..b8af76e 100644 --- a/native/projects/lcpu/src/SourceSink.cpp +++ b/native/projects/lcpu/src/SourceSink.cpp @@ -11,7 +11,6 @@ #define LCPU_SUPPORT_OLD_GMOD namespace tier0 { - // TODO: For now this'll leak.. lucore::Library* library = nullptr; using Msg_t = void (*)(const char*, ...); diff --git a/native/projects/lcpu/src/main.cpp b/native/projects/lcpu/src/main.cpp index c671f09..101e20b 100644 --- a/native/projects/lcpu/src/main.cpp +++ b/native/projects/lcpu/src/main.cpp @@ -6,13 +6,19 @@ #include "LcpuGlobals.hpp" +#include "LuaShared.hpp" + GMOD_MODULE_OPEN() { lucore::Logger::The().AttachSink(lcpu::SourceSink::The()); lucore::LogInfo("LCPU Native Module! (ModuleVersion {})", LCPU_MODULE_VERSION); + + lcpu::lua::LoadLuaShared(); + GlobalsBind(LUA); return 0; } GMOD_MODULE_CLOSE() { + lcpu::lua::UnloadLuaShared(); return 0; } diff --git a/native/projects/lucore/include/lucore/Logger.hpp b/native/projects/lucore/include/lucore/Logger.hpp index ce6bd9e..a096172 100644 --- a/native/projects/lucore/include/lucore/Logger.hpp +++ b/native/projects/lucore/include/lucore/Logger.hpp @@ -84,22 +84,27 @@ namespace lucore { }; template - void LogInfo(std::string_view format, Args... args) { + constexpr void LogDebug(std::string_view format, Args... args) { + Logger::The().Debug(format, std::forward(args)...); + } + + template + constexpr void LogInfo(std::string_view format, Args... args) { Logger::The().Info(format, std::forward(args)...); } template - void LogWarning(std::string_view format, Args... args) { + constexpr void LogWarning(std::string_view format, Args... args) { Logger::The().Warning(format, std::forward(args)...); } template - void LogError(std::string_view format, Args... args) { + constexpr void LogError(std::string_view format, Args... args) { Logger::The().Error(format, std::forward(args)...); } template - void LogFatal(std::string_view format, Args... args) { + constexpr void LogFatal(std::string_view format, Args... args) { Logger::The().Fatal(format, std::forward(args)...); } diff --git a/native/projects/lucore/src/Library.cpp b/native/projects/lucore/src/Library.cpp index e95f7da..daac631 100644 --- a/native/projects/lucore/src/Library.cpp +++ b/native/projects/lucore/src/Library.cpp @@ -18,8 +18,17 @@ namespace lucore { Library* Library::OpenExisting(std::string_view dllname) { auto name = FormatLibraryName(dllname); - if(!detail::OsLibraryLoaded(name.c_str())) + if(!detail::OsLibraryLoaded(name.c_str())) { +#ifndef _WIN32 + // Try without a prefix; some libraries need this. + name = std::format("{}.so", dllname); + if(!detail::OsLibraryLoaded(name.c_str())) + return nullptr; +#else return nullptr; +#endif + } + return new Library(detail::OsOpenLibrary(name.c_str())); }