2
0
mirror of https://github.com/boostorg/dll.git synced 2026-02-19 02:12:23 +00:00

Simplified code and unified load_mode::append_decorations behavior on different platforms

This commit is contained in:
Antony Polukhin
2015-08-01 14:45:14 +03:00
parent d6afc013bf
commit a0a43b3ece
3 changed files with 57 additions and 45 deletions

View File

@@ -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<int>(mode));
} else {
// Trying to open with appended decorations
if (!!(mode & load_mode::append_decorations)) {
mode = static_cast<load_mode::type>(
static_cast<native_mode_t>(mode) & (~static_cast<native_mode_t>(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<int>(mode) & (~static_cast<int>(load_mode::append_decorations))
);
handle_ = dlopen(actual_path.c_str(), static_cast<native_mode_t>(mode));
if (handle_) {
return;
}
}
// Opening by exactly specified path
handle_ = dlopen(sl.c_str(), static_cast<native_mode_t>(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<int>(mode) & (~static_cast<int>(load_mode::append_decorations)));
ec.clear();
handle_ = dlopen(NULL, static_cast<native_mode_t>(mode));
if (!handle_) {
ec = boost::system::error_code(
boost::system::errc::bad_file_descriptor,

View File

@@ -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<boost::detail::winapi::DWORD_>(mode);
// Trying to open with appended decorations
if (!!(mode & load_mode::append_decorations)) {
mode = static_cast<load_mode::type>(
static_cast<native_mode_t>(mode) & (~static_cast<native_mode_t>(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<boost::detail::winapi::DWORD_>(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<native_mode_t>(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<native_mode_t>(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<native_mode_t>(mode));
} else {
handle_ = boost::detail::winapi::LoadLibraryExW((sl.native() + L".").c_str(), 0, static_cast<native_mode_t>(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();
}

View File

@@ -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
*/