diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8671ee4c..2b2953bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,6 +18,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v2.3.4 + with: + submodules: 'true' - name: Setup .NET Core SDK uses: actions/setup-dotnet@v1.7.2 @@ -135,6 +137,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v2.3.4 + with: + submodules: 'true' - name: Setup .NET Core SDK uses: actions/setup-dotnet@v1.7.2 @@ -245,6 +249,8 @@ jobs: - name: Checkout uses: actions/checkout@v2.3.4 + with: + submodules: 'true' - name: Setup .NET Core SDK uses: actions/setup-dotnet@v1.7.2 @@ -311,6 +317,8 @@ jobs: - name: Checkout repository uses: actions/checkout@v2.3.4 + with: + submodules: 'true' - name: Setup .NET Core SDK uses: actions/setup-dotnet@v1.7.2 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..7983dcf8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "dynalo"] + path = gm_dotnet_native/external_includes/dynalo + url = https://github.com/Stat1cV01D/dynalo.git diff --git a/README.md b/README.md index 49cb83b1..c4cc6487 100644 --- a/README.md +++ b/README.md @@ -112,4 +112,6 @@ Gmod.NET is making use of or borrows code from the following projects: 4. [Libsodium](http://libsodium.org) by [Frank Denis](https://github.com/jedisct1) (ISC License) +5. [dynalo](https://github.com/Stat1cV01D/dynalo) originally by [maddouri](https://github.com/maddouri/dynalo) (MIT License) + See other copyright notices in the NOTICE file. diff --git a/gm_dotnet_native/CMakeLists.txt b/gm_dotnet_native/CMakeLists.txt index a7ffb4e3..a2ae11f2 100644 --- a/gm_dotnet_native/CMakeLists.txt +++ b/gm_dotnet_native/CMakeLists.txt @@ -25,7 +25,10 @@ add_library(gm_dotnet_native SHARED src/gm_dotnet.cpp dotnethelper-src/cleanup_f add_library(dotnethelper SHARED dotnethelper-src/dotnethelper.cpp dotnethelper-src/cleanup_function_type.h dotnethelper-src/LuaAPIExposure.h dotnethelper-src/LuaAPIExposure.cpp) #Set up external include libraries -include_directories ("${EXTERNAL_INCLUDES_PATH}") +include_directories ("${EXTERNAL_INCLUDES_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}") +add_subdirectory ("${EXTERNAL_INCLUDES_PATH}/dynalo") +target_link_libraries(gm_dotnet_native PUBLIC dynalo) +target_link_libraries(dotnethelper PUBLIC dynalo) #Set up compile definitions target_compile_definitions(gm_dotnet_native PUBLIC SEM_VERSION="${SEM_VERSION}") target_compile_definitions(dotnethelper PUBLIC SEM_VERSION="${SEM_VERSION}") diff --git a/gm_dotnet_native/dotnethelper-src/dotnethelper.cpp b/gm_dotnet_native/dotnethelper-src/dotnethelper.cpp index 60db6736..de12b087 100644 --- a/gm_dotnet_native/dotnethelper-src/dotnethelper.cpp +++ b/gm_dotnet_native/dotnethelper-src/dotnethelper.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef WIN32 #include #else @@ -51,23 +52,13 @@ managed_main_fn managed_main = nullptr; const std::filesystem::path lua_bin_folder = _T("garrysmod/lua/bin"); const std::filesystem::path hostfxr_path = (lua_bin_folder / _T("dotnet/host/fxr") / NET_CORE_VERSION).make_preferred(); -#ifdef WIN32 -HMODULE hostfxr_library_handle = LoadLibraryW((hostfxr_path / _T("hostfxr.dll")).c_str()); -#elif __APPLE__ -void* hostfxr_library_handle = dlopen((hostfxr_path / "libhostfxr.dylib").c_str(), RTLD_LAZY | RTLD_LOCAL); -#elif __gnu_linux__ -void* hostfxr_library_handle = dlopen((hostfxr_path / "libhostfxr.so").c_str(), RTLD_LAZY); -#endif + +const dynalo::library hostfxr_library(hostfxr_path / dynalo::to_native_name("hostfxr")); template -bool LoadFunction(const char* function_name, T& out_func) +void load_hostfxr_function(const char* function_name, T& out_func) { -#ifdef WIN32 - out_func = reinterpret_cast(GetProcAddress(hostfxr_library_handle, function_name)); -#else - out_func = reinterpret_cast(dlsym(hostfxr_library_handle, function_name)); -#endif - return (out_func != nullptr); + out_func = hostfxr_library.get_function>(function_name); } hostfxr_initialize_for_dotnet_command_line_fn hostfxr_initialize_for_dotnet_command_line = nullptr; hostfxr_get_runtime_delegate_fn hostfxr_get_runtime_delegate = nullptr; @@ -161,11 +152,15 @@ extern "C" DYNAMIC_EXPORT cleanup_function_fn InitNetRuntime(GarrysMod::Lua::ILu if(managed_main == nullptr) { - if(!(LoadFunction("hostfxr_initialize_for_dotnet_command_line", hostfxr_initialize_for_dotnet_command_line) - && LoadFunction("hostfxr_get_runtime_delegate", hostfxr_get_runtime_delegate) - && LoadFunction("hostfxr_set_error_writer", hostfxr_set_error_writer))) + try + { + load_hostfxr_function("hostfxr_initialize_for_dotnet_command_line", hostfxr_initialize_for_dotnet_command_line); + load_hostfxr_function("hostfxr_get_runtime_delegate", hostfxr_get_runtime_delegate); + load_hostfxr_function("hostfxr_set_error_writer", hostfxr_set_error_writer); + } + catch (std::runtime_error ex) { - error_log_file << "Unable to load hostfxr library" << std::endl; + error_log_file << "Unable to load hostfxr library: " << ex.what() << std::endl; return nullptr; } @@ -199,6 +194,7 @@ extern "C" DYNAMIC_EXPORT cleanup_function_fn InitNetRuntime(GarrysMod::Lua::ILu if(runtime_environment_handle == nullptr) { error_log_file << "runtime_environment_handle is null" << std::endl; + return nullptr; } get_function_pointer_fn get_function_pointer = nullptr; int get_runtime_delegate_success_code = diff --git a/gm_dotnet_native/external_includes/dynalo b/gm_dotnet_native/external_includes/dynalo new file mode 160000 index 00000000..a1adfd99 --- /dev/null +++ b/gm_dotnet_native/external_includes/dynalo @@ -0,0 +1 @@ +Subproject commit a1adfd9963959354a1a4ebac9da3f7f280bf6487 diff --git a/gm_dotnet_native/src/gm_dotnet.cpp b/gm_dotnet_native/src/gm_dotnet.cpp index 29c862bb..761627f9 100644 --- a/gm_dotnet_native/src/gm_dotnet.cpp +++ b/gm_dotnet_native/src/gm_dotnet.cpp @@ -10,22 +10,25 @@ #include #endif // WIN32 #include -#include "../dotnethelper-src/cleanup_function_type.h" - -typedef cleanup_function_fn (*InitNetRuntime_fn)(GarrysMod::Lua::ILuaBase* lua); +#include "dotnethelper-src/cleanup_function_type.h" +#include cleanup_function_fn cleanup_function = nullptr; +const std::filesystem::path lua_bin_folder("garrysmod/lua/bin"); + +#ifdef __gnu_linux__ +const dynalo::library liblinuxhelper(lua_bin_folder / "liblinuxhelper.so"); +#endif + +const dynalo::library dotnethelper(lua_bin_folder / dynalo::to_native_name("dotnethelper")); + //Invoked by Garry's Mod on module load GMOD_MODULE_OPEN() { - const std::filesystem::path lua_bin_folder("garrysmod/lua/bin"); - // On Linux, modify SIGSEGV handling #ifdef __gnu_linux__ - void *linux_helper_handle = dlopen((lua_bin_folder / "liblinuxhelper.so").c_str(), RTLD_LAZY); - void (*pointer_to_install_sigsegv)(void); - pointer_to_install_sigsegv = (void(*)())dlsym(linux_helper_handle, "install_sigsegv_handler"); + auto pointer_to_install_sigsegv = liblinuxhelper.get_function("install_sigsegv_handler"); pointer_to_install_sigsegv(); #endif @@ -36,36 +39,22 @@ GMOD_MODULE_OPEN() LUA->Call(1, 0); LUA->Pop(1); - InitNetRuntime_fn InitNetRuntime = nullptr; - const char InitNetRuntime_fn_name[] = "InitNetRuntime"; - -#ifdef WIN32 - HMODULE dotnethelper_handle = LoadLibraryW((lua_bin_folder / "dotnethelper.dll").make_preferred().c_str()); - if (dotnethelper_handle != nullptr) - InitNetRuntime = reinterpret_cast(GetProcAddress(dotnethelper_handle, InitNetRuntime_fn_name)); -#elif __APPLE__ - void* dotnethelper_handle = dlopen((lua_bin_folder / "libdotnethelper.dylib").c_str(), RTLD_LAZY); -#elif __gnu_linux__ - void* dotnethelper_handle = dlopen((lua_bin_folder / "libdotnethelper.so").c_str(), RTLD_LAZY); -#endif - -#ifndef WIN32 - InitNetRuntime = reinterpret_cast(dlsym(dotnethelper_handle, InitNetRuntime_fn_name)); -#endif - - if(InitNetRuntime == nullptr) + try { + auto InitNetRuntime = dotnethelper.get_function("InitNetRuntime"); + cleanup_function = InitNetRuntime(LUA); + } + catch(std::runtime_error e) + { + auto error_msg = std::string("::error::Unable to load dotnet helper library. ") + e.what(); LUA->PushSpecial(GarrysMod::Lua::SPECIAL_GLOB); LUA->GetField(-1, "print"); - LUA->PushString("::error::Unable to load dotnet helper library."); + LUA->PushString(error_msg.c_str()); LUA->Call(1, 0); LUA->Pop(1); - return 0; } - cleanup_function = InitNetRuntime(LUA); - if(cleanup_function == nullptr) { LUA->PushSpecial(GarrysMod::Lua::SPECIAL_GLOB);