summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/plugin/qlibrary.cpp23
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp17
-rw-r--r--src/corelib/plugin/qlibrary_win.cpp73
3 files changed, 80 insertions, 33 deletions
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 8e69960c93..3815082989 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -96,13 +96,22 @@ static QBasicMutex qt_library_mutex;
name in the constructor, or set it explicitly with setFileName().
When loading the library, QLibrary searches in all the
system-specific library locations (e.g. \c LD_LIBRARY_PATH on
- Unix), unless the file name has an absolute path. If the file
- cannot be found, QLibrary tries the name with different
- platform-specific file suffixes, like ".so" on Unix, ".dylib" on
- the Mac, or ".dll" on Windows. This makes it possible
- to specify shared libraries that are only identified by their
- basename (i.e. without their suffix), so the same code will work
- on different operating systems.
+ Unix), unless the file name has an absolute path.
+
+ If the file name is an absolute path then an attempt is made to
+ load this path first. If the file cannot be found, QLibrary tries
+ the name with different platform-specific file prefixes, like
+ "lib" on Unix and Mac, and suffixes, like ".so" on Unix, ".dylib"
+ on the Mac, or ".dll" on Windows.
+
+ If the file path is not absolute then QLibrary modifies the search
+ order to try the system-specific prefixes and suffixes first,
+ followed by the file path specified.
+
+ This makes it possible to specify shared libraries that are only
+ identified by their basename (i.e. without their suffix), so the
+ same code will work on different operating systems yet still
+ minimise the number of attempts to find the library.
The most important functions are load() to dynamically load the
library file, isLoaded() to check whether loading was successful,
diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp
index abfbeb25d4..0ad9f690d5 100644
--- a/src/corelib/plugin/qlibrary_unix.cpp
+++ b/src/corelib/plugin/qlibrary_unix.cpp
@@ -93,9 +93,8 @@ bool QLibraryPrivate::load_sys()
else
path += QLatin1Char('/');
- // The first filename we want to attempt to load is the filename as the callee specified.
- // Thus, the first attempt we do must be with an empty prefix and empty suffix.
- QStringList suffixes(QLatin1String("")), prefixes(QLatin1String(""));
+ QStringList suffixes;
+ QStringList prefixes;
if (pluginState != IsAPlugin) {
prefixes << QLatin1String("lib");
#if defined(Q_OS_HPUX)
@@ -185,6 +184,18 @@ bool QLibraryPrivate::load_sys()
}
#endif
#endif // QT_HPUX_LD
+
+ // If the filename is an absolute path then we want to try that first as it is most likely
+ // what the callee wants. If we have been given a non-absolute path then lets try the
+ // native library name first to avoid unnecessary calls to dlopen().
+ if (fsEntry.isAbsolute()) {
+ suffixes.prepend(QString());
+ prefixes.prepend(QString());
+ } else {
+ suffixes.append(QString());
+ prefixes.append(QString());
+ }
+
bool retry = true;
for(int prefix = 0; retry && !pHnd && prefix < prefixes.size(); prefix++) {
for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) {
diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp
index 1e8ab150b5..10ca17cd2d 100644
--- a/src/corelib/plugin/qlibrary_win.cpp
+++ b/src/corelib/plugin/qlibrary_win.cpp
@@ -45,6 +45,7 @@
#include "qdir.h"
#include "qfileinfo.h"
#include "qdir.h"
+#include <private/qfilesystementry_p.h>
#if defined(QT_NO_LIBRARY) && defined(Q_OS_WIN)
#undef QT_NO_LIBRARY
@@ -59,46 +60,72 @@ extern QString qt_error_string(int code);
bool QLibraryPrivate::load_sys()
{
-#ifdef Q_OS_WINCE
- QString attempt = QFileInfo(fileName).absoluteFilePath();
-#else
- QString attempt = fileName;
-#endif
-
//avoid 'Bad Image' message box
UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
- pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
- if (pluginState != IsAPlugin) {
+ // We make the following attempts at locating the library:
+ //
+ // WinCE
+ // if (absolute)
+ // fileName
+ // fileName + ".dll"
+ // else
+ // fileName + ".dll"
+ // fileName
+ // QFileInfo(fileName).absoluteFilePath()
+ //
+ // Windows
+ // if (absolute)
+ // fileName
+ // fileName + ".dll"
+ // else
+ // fileName + ".dll"
+ // fileName
+ //
+ // NB If it's a plugin we do not ever try the ".dll" extension
+ QStringList attempts;
+
+ if (pluginState != IsAPlugin)
+ attempts.append(fileName + QLatin1String(".dll"));
+
+ // If the fileName is an absolute path we try that first, otherwise we
+ // use the system-specific suffix first
+ QFileSystemEntry fsEntry(fileName);
+ if (fsEntry.isAbsolute()) {
+ attempts.prepend(fileName);
+ } else {
+ attempts.append(fileName);
#if defined(Q_OS_WINCE)
- if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) {
- QString secondAttempt = fileName;
- pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(secondAttempt).utf16());
- }
+ attempts.append(QFileInfo(fileName).absoluteFilePath());
#endif
- if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) {
- attempt += QLatin1String(".dll");
- pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
- }
+ }
+
+ Q_FOREACH (const QString &attempt, attempts) {
+ pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16());
+
+ // If we have a handle or the last error is something other than "unable
+ // to find the module", then bail out
+ if (pHnd || ::GetLastError() != ERROR_MOD_NOT_FOUND)
+ break;
}
SetErrorMode(oldmode);
if (!pHnd) {
errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName).arg(qt_error_string());
- }
- if (pHnd) {
+ } else {
+ // Query the actual name of the library that was loaded
errorString.clear();
wchar_t buffer[MAX_PATH];
::GetModuleFileName(pHnd, buffer, MAX_PATH);
- attempt = QString::fromWCharArray(buffer);
- const QDir dir = QFileInfo(fileName).dir();
- const QString realfilename = attempt.mid(attempt.lastIndexOf(QLatin1Char('\\')) + 1);
+ QString moduleFileName = QString::fromWCharArray(buffer);
+ moduleFileName.remove(0, 1 + moduleFileName.lastIndexOf(QLatin1Char('\\')));
+ const QDir dir(fsEntry.path());
if (dir.path() == QLatin1String("."))
- qualifiedFileName = realfilename;
+ qualifiedFileName = moduleFileName;
else
- qualifiedFileName = dir.filePath(realfilename);
+ qualifiedFileName = dir.filePath(moduleFileName);
}
return (pHnd != 0);
}