diff --git a/include/boost/dll/detail/posix/shared_library_impl.hpp b/include/boost/dll/detail/posix/shared_library_impl.hpp index bfcf7c8..533d57a 100644 --- a/include/boost/dll/detail/posix/shared_library_impl.hpp +++ b/include/boost/dll/detail/posix/shared_library_impl.hpp @@ -60,9 +60,10 @@ public: } void load(const boost::filesystem::path &sl, load_mode::type mode, boost::system::error_code &ec) { + typedef int native_mode_t; unload(); - // Do not allow opening NULL paths. User must use load_self() instead + // Do not allow opening NULL paths. User must use program_location() instead if (sl.empty()) { ec = boost::system::error_code( boost::system::errc::bad_file_descriptor, @@ -73,17 +74,20 @@ public: } // Fixing modes - if (!(mode & RTLD_LAZY || mode & RTLD_NOW)) { + if (!(mode & load_mode::rtld_now)) { mode |= load_mode::rtld_lazy; } - if (!(mode & RTLD_LOCAL || mode & RTLD_GLOBAL)) { + if (!(mode & load_mode::rtld_global)) { mode |= load_mode::rtld_local; } - if (!(mode & load_mode::append_decorations)) { - handle_ = dlopen(sl.c_str(), static_cast(mode)); - } else { + // Trying to open with appended decorations + if (!!(mode & load_mode::append_decorations)) { + mode = static_cast( + static_cast(mode) & (~static_cast(load_mode::append_decorations)) + ); + boost::filesystem::path actual_path = ( std::strncmp(sl.filename().string().c_str(), "lib", 3) ? (sl.parent_path() / "lib").native() + sl.filename().native() @@ -91,12 +95,14 @@ public: ); actual_path += suffix(); - handle_ = dlopen( - actual_path.c_str(), - static_cast(mode) & (~static_cast(load_mode::append_decorations)) - ); + handle_ = dlopen(actual_path.c_str(), static_cast(mode)); + if (handle_) { + return; + } } + // Opening by exactly specified path + handle_ = dlopen(sl.c_str(), static_cast(mode)); if (handle_) { return; } @@ -116,8 +122,8 @@ public: // named by the null-terminated string filename and returns an opaque // "handle" for the dynamic library. If filename is NULL, then the // returned handle is for the main program. - handle_ = dlopen(NULL, static_cast(mode) & (~static_cast(load_mode::append_decorations))); ec.clear(); + handle_ = dlopen(NULL, static_cast(mode)); if (!handle_) { ec = boost::system::error_code( boost::system::errc::bad_file_descriptor, diff --git a/include/boost/dll/detail/windows/shared_library_impl.hpp b/include/boost/dll/detail/windows/shared_library_impl.hpp index 37065b2..c0f2a6a 100644 --- a/include/boost/dll/detail/windows/shared_library_impl.hpp +++ b/include/boost/dll/detail/windows/shared_library_impl.hpp @@ -40,55 +40,59 @@ public: unload(); } - shared_library_impl(BOOST_RV_REF(shared_library_impl) sl) - { - handle_ = sl.handle_; sl.handle_ = NULL; + shared_library_impl(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT + : handle_(sl.handle_) + { + sl.handle_ = NULL; } - shared_library_impl & operator=(BOOST_RV_REF(shared_library_impl) sl) - { - handle_ = sl.handle_; sl.handle_ = NULL; return *this; + shared_library_impl & operator=(BOOST_RV_REF(shared_library_impl) sl) BOOST_NOEXCEPT { + handle_ = sl.handle_; + sl.handle_ = NULL; + return *this; } - void load(const boost::filesystem::path &sl, load_mode::type mode, boost::system::error_code &ec) BOOST_NOEXCEPT { + void load(const boost::filesystem::path &sl, load_mode::type mode, boost::system::error_code &ec) { + typedef boost::detail::winapi::DWORD_ native_mode_t; unload(); - boost::detail::winapi::DWORD_ flags = static_cast(mode); + // Trying to open with appended decorations + if (!!(mode & load_mode::append_decorations)) { + mode = static_cast( + static_cast(mode) & (~static_cast(load_mode::append_decorations) + ); - // From MSDN: If the string specifies a module name without a path and the - // file name extension is omitted, the function appends the default library - // extension .dll to the module name. - // - // From experiments: Default library extension appended to the modukle name even if - // we have some path. So we do not check for path, only for extension. We can not be sure that - // such behavior remain across all platforms, so we add L".dll" by hand. - const bool do_append_deco = !!(mode & load_mode::append_decorations); - if (!do_append_deco && sl.has_extension()) { - handle_ = boost::detail::winapi::LoadLibraryExW(sl.c_str(), 0, flags); - } else if (!do_append_deco) { - handle_ = boost::detail::winapi::LoadLibraryExW((sl.native() + L".").c_str(), 0, flags); - } else { - flags &= ~static_cast(load_mode::append_decorations); - handle_ = boost::detail::winapi::LoadLibraryExW((sl.native() + L".dll").c_str(), 0, flags); + handle_ = boost::detail::winapi::LoadLibraryExW((sl.native() + L".dll").c_str(), 0, static_cast(mode)); if (!handle_) { // MinGW loves 'lib' prefix and puts it even on Windows platform handle_ = boost::detail::winapi::LoadLibraryExW( - ((sl.parent_path() / L"lib").native() + sl.filename().native() + L".dll").c_str(), 0, flags); + ((sl.parent_path() / L"lib").native() + sl.filename().native() + L".dll").c_str(), + 0, + static_cast(mode) + ); } if (handle_) { return; } - - ec = boost::dll::detail::last_error_code(); - - // Possibly we were attempting to load an executable, then decorations must not be applied - handle_ = boost::detail::winapi::LoadLibraryExW(sl.c_str(), 0, flags); - if (handle_) { - ec.clear(); - } } + // From MSDN: If the string specifies a module name without a path and the + // file name extension is omitted, the function appends the default library + // extension .dll to the module name. + // + // From experiments: Default library extension appended to the module name even if + // we have some path. So we do not check for path, only for extension. We can not be sure that + // such behavior remain across all platforms, so we add L".dll" by hand. + if (sl.has_extension()) { + handle_ = boost::detail::winapi::LoadLibraryExW(sl.c_str(), 0, static_cast(mode)); + } else { + handle_ = boost::detail::winapi::LoadLibraryExW((sl.native() + L".").c_str(), 0, static_cast(mode)); + } + + // LoadLibraryExW method is capable of self loading from program_location() path. No special actions + // must be taken to allow self loading. + if (!handle_) { ec = boost::dll::detail::last_error_code(); } diff --git a/include/boost/dll/shared_library_load_mode.hpp b/include/boost/dll/shared_library_load_mode.hpp index da3c83f..73f421f 100644 --- a/include/boost/dll/shared_library_load_mode.hpp +++ b/include/boost/dll/shared_library_load_mode.hpp @@ -192,11 +192,13 @@ enum type { * * \b Default: disabled * - * Append a platform specific extension and prefix to shared_library filename. + * Append a platform specific extension and prefix to shared library filename before trying to load it. + * If load attempt fails, try to load with exactly specified name. * * \b Example: * \code - * // Opens `./my_plugins/plugin1.dll` on Windows, `./my_plugins/libplugin1.so` on Linux and Apple + * // Opens `./my_plugins/plugin1.dll` on Windows, `./my_plugins/libplugin1.so` on Linux, `./my_plugins/libplugin1.dylib` on MacOS. + * // If that fails, loads `./my_plugins/plugin1` * boost::dll::shared_library lib("./my_plugins/plugin1", load_mode::append_decorations); * \endcode */