diff --git a/src/thorin/plugin.cpp b/src/thorin/plugin.cpp index 0746f7e71..fa154f153 100644 --- a/src/thorin/plugin.cpp +++ b/src/thorin/plugin.cpp @@ -10,40 +10,51 @@ #endif namespace thorin { -bool World::load_plugin(const char* plugin_name) { +[[nodiscard]] static void* load_plugin_module(const char* plugin_name) { #ifdef _WIN32 - return false; + return LoadLibraryA(plugin_name); #else - void *handle = dlopen(plugin_name, RTLD_LAZY | RTLD_GLOBAL); - if (!handle) { - ELOG("Error loading plugin {}: {}", plugin_name, dlerror()); - ELOG("Is plugin contained in LD_LIBRARY_PATH?"); - return false; - } - dlerror(); - - char *error; - auto initfunc = reinterpret_cast(dlsym(handle, "init")); - if ((error = dlerror()) != NULL) { - ILOG("Plugin {} did not supply an init function", plugin_name); - } else { - initfunc(); - } + return dlopen(plugin_name, RTLD_LAZY | RTLD_GLOBAL); +#endif +} - data_.plugin_modules_.push_back(handle); - return true; +static bool unload_plugin_module(void* plugin_module) { +#ifdef _WIN32 + return FreeLibrary(static_cast(plugin_module)) == TRUE; +#else + return dlclose(plugin_module) == 0; #endif } template -static T* lookup_plugin_function(void* plugin_module, const char* function_name) { +[[nodiscard]] static T* lookup_plugin_function(void* plugin_module, const char* function_name) { #ifdef _WIN32 + return reinterpret_cast(GetProcAddress(static_cast(plugin_module), function_name)); #else - if (void* func = dlsym(plugin_module, function_name)) { - return reinterpret_cast(func); - } + return reinterpret_cast(dlsym(plugin_module, function_name)); #endif - return nullptr; +} + +bool World::load_plugin(const char* plugin_name) { + void* module = load_plugin_module(plugin_name); + + if (!module) { + ELOG("failed to load plugin {}", plugin_name); + return false; + } + + if (auto init = lookup_plugin_function(module, "init")) { + if (!init()) { + ELOG("failed to initialize plugin {}", plugin_name); + unload_plugin_module(module); + return false; + } + } else { + ILOG("plugin {} did not supply an init function", plugin_name); + } + + data_.plugin_modules_.push_back(module); + return true; } unique_plugin_intrinsic World::load_plugin_intrinsic(const char* function_name) const { diff --git a/src/thorin/plugin.h b/src/thorin/plugin.h index a4d8e0487..bc2b5c268 100644 --- a/src/thorin/plugin.h +++ b/src/thorin/plugin.h @@ -31,7 +31,7 @@ namespace thorin { using unique_plugin_intrinsic = std::unique_ptr; extern "C" { - using plugin_init_func_t = void(); + using plugin_init_func_t = bool(); using plugin_intrinsic_create_func_t = plugin_intrinsic*(); } }