| 24 | } |
| 25 | |
| 26 | bool ModuleLoader::load(const std::string& name) |
| 27 | { |
| 28 | if (modules.find(name) != modules.end()) |
| 29 | return true; // module already loaded |
| 30 | |
| 31 | // Get the path of the module to load |
| 32 | std::string filename = OIDN_LIBRARY_NAME "_" + name; |
| 33 | #if defined(_WIN32) |
| 34 | filename += ".dll"; |
| 35 | #else |
| 36 | #if defined(OIDN_LIBRARY_VERSIONED) |
| 37 | const std::string versionStr = "." OIDN_VERSION_STRING_SHORT; |
| 38 | #else |
| 39 | const std::string versionStr = ""; |
| 40 | #endif |
| 41 | #if defined(__APPLE__) |
| 42 | filename = "lib" + filename + versionStr + ".dylib"; |
| 43 | #else |
| 44 | filename = "lib" + filename + ".so" + versionStr; |
| 45 | #endif |
| 46 | #endif |
| 47 | |
| 48 | const Path path = modulePathPrefix + Path(filename.begin(), filename.end()); |
| 49 | |
| 50 | // Load the module |
| 51 | #if defined(_WIN32) |
| 52 | // Prevent the system from displaying a message box when the module fails to load |
| 53 | UINT prevErrorMode = GetErrorMode(); |
| 54 | SetErrorMode(prevErrorMode | SEM_FAILCRITICALERRORS); |
| 55 | void* module = LoadLibraryW(path.c_str()); |
| 56 | SetErrorMode(prevErrorMode); |
| 57 | #else |
| 58 | void* module = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL); |
| 59 | #endif |
| 60 | if (module == nullptr) |
| 61 | return false; |
| 62 | |
| 63 | // Get the address of the module init function |
| 64 | const std::string initSymbol = |
| 65 | (OIDN_TO_STRING(OIDN_NAMESPACE_C) "_init_module_") + name + ("_v" OIDN_TO_STRING(OIDN_VERSION)); |
| 66 | void* initAddress = getSymbolAddress(module, initSymbol); |
| 67 | if (initAddress == nullptr) |
| 68 | { |
| 69 | Context::get().printWarning("invalid module: '" + filename + "'"); |
| 70 | closeModule(module); |
| 71 | return false; |
| 72 | } |
| 73 | |
| 74 | // Call the module init function |
| 75 | auto initFunc = reinterpret_cast<void (*)()>(initAddress); |
| 76 | initFunc(); |
| 77 | |
| 78 | // The module has been loaded successfully. |
| 79 | // We won't unload the module manually to avoid issues due to the undefined module unloading |
| 80 | // and static object destruction order at process exit. This intentional "leak" is fine |
| 81 | // because the modules are owned by the context which is static, and the modules will be |
| 82 | // unloaded at process exit anyway. Thus we don't need the module handle anymore. |
| 83 | modules.insert(name); |