diff options
-rw-r--r-- | src/corelib/plugin/qlibrary.cpp | 23 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary_unix.cpp | 17 | ||||
-rw-r--r-- | src/corelib/plugin/qlibrary_win.cpp | 73 |
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); } |