#include "Core.h" #include "Debug.h" #include "Export.h" #include "PluginManager.h" #include "Hooks.h" #include #include #include #include #include #include #ifdef WIN32 #define NOMINMAX #include #define global_search_handle() GetModuleHandle(nullptr) #define get_function_address(plugin, function) GetProcAddress((HMODULE)plugin, function) #define clear_error() #define load_library(fn) LoadLibraryW(fn.c_str()) #define close_library(handle) (!(FreeLibrary((HMODULE)handle))) #else #include #include #include #include #include #include #include #include #include #define global_search_handle() (RTLD_DEFAULT) #define get_function_address(plugin, function) dlsym((void*)plugin, function) #define clear_error() dlerror() #define load_library(fn) dlopen(fn.c_str(), RTLD_NOW | RTLD_LOCAL); #define close_library(handle) dlclose((void*)handle) #endif /* * Plugin loading functions */ namespace DFHack { DBG_DECLARE(core, plugins, DebugCategory::LINFO); DFHack::DFLibrary* GLOBAL_NAMES = (DFLibrary*)global_search_handle(); namespace { std::string get_error() { #ifdef WIN32 DWORD error = GetLastError(); LPSTR buf = NULL; DWORD len = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buf, 0, NULL); if (len > 0) { std::string message{ buf }; LocalFree(buf); return message; } std::ostringstream b{}; b << "unknown error " << error; return b.str(); #else char* error = dlerror(); if (error) return std::string{ error }; return std::string{}; #endif } } DFLibrary * OpenPlugin (std::filesystem::path filename) { clear_error(); DFLibrary* ret = (DFLibrary*)load_library(filename); if (!ret) { auto error = get_error(); WARN(plugins).print("OpenPlugin on {} failed: {}\n", filename.string(), error); } return ret; } void * LookupPlugin (DFLibrary * plugin ,const char * function) { return (void *) get_function_address(plugin, function); } bool ClosePlugin (DFLibrary * plugin) { int res = close_library(plugin); if (res != 0) { auto error = get_error(); WARN(plugins).print("ClosePlugin failed: {}\n", error); } return (res == 0); } }