qpluginloader.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/corelib/plugin/qpluginloader.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtCore module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qplatformdefs.h"-
41-
42#include "qplugin.h"-
43#include "qcoreapplication.h"-
44#include "qpluginloader.h"-
45#include <qfileinfo.h>-
46#include "qlibrary_p.h"-
47#include "qdebug.h"-
48#include "qdir.h"-
49-
50QT_BEGIN_NAMESPACE-
51-
52#ifndef QT_NO_LIBRARY-
53-
QT_BEGIN_NAMESPACE/*!
55 \class QPluginLoader-
56 \inmodule QtCore-
57 \reentrant-
58 \brief The QPluginLoader class loads a plugin at run-time.-
59-
60-
61 \ingroup plugins-
62-
63 QPluginLoader provides access to a \l{How to Create Qt-
64 Plugins}{Qt plugin}. A Qt plugin is stored in a shared library (a-
65 DLL) and offers these benefits over shared libraries accessed-
66 using QLibrary:-
67-
68 \list-
69 \li QPluginLoader checks that a plugin is linked against the same-
70 version of Qt as the application.-
71 \li QPluginLoader provides direct access to a root component object-
72 (instance()), instead of forcing you to resolve a C function manually.-
73 \endlist-
74-
75 An instance of a QPluginLoader object operates on a single shared-
76 library file, which we call a plugin. It provides access to the-
77 functionality in the plugin in a platform-independent way. To-
78 specify which plugin to load, either pass a file name in-
79 the constructor or set it with setFileName().-
80-
81 The most important functions are load() to dynamically load the-
82 plugin file, isLoaded() to check whether loading was successful,-
83 and instance() to access the root component in the plugin. The-
84 instance() function implicitly tries to load the plugin if it has-
85 not been loaded yet. Multiple instances of QPluginLoader can be-
86 used to access the same physical plugin.-
87-
88 Once loaded, plugins remain in memory until all instances of-
89 QPluginLoader has been unloaded, or until the application-
90 terminates. You can attempt to unload a plugin using unload(),-
91 but if other instances of QPluginLoader are using the same-
92 library, the call will fail, and unloading will only happen when-
93 every instance has called unload(). Right before the unloading-
94 happen, the root component will also be deleted.-
95-
96 See \l{How to Create Qt Plugins} for more information about-
97 how to make your application extensible through plugins.-
98-
99 Note that the QPluginLoader cannot be used if your application is-
100 statically linked against Qt. In this case, you will also have to-
101 link to plugins statically. You can use QLibrary if you need to-
102 load dynamic libraries in a statically linked application.-
103-
104 \sa QLibrary, {Plug & Paint Example}-
105*/-
106-
107/*!-
108 \class QStaticPlugin-
109 \inmodule QtCore-
110 \since 5.2-
111-
112 \brief QStaticPlugin is a struct containing a reference to a-
113 static plugin instance together with its meta data.-
114-
115 \sa QPluginLoader, {How to Create Qt Plugins}-
116*/-
117-
118/*!-
119 \fn QObject *QStaticPlugin::instance()-
120-
121 Returns the plugin instance.-
122-
123 \sa QPluginLoader::staticInstances()-
124*/-
125-
126/*!-
127 \fn const char *QStaticPlugin::rawMetaData()-
128-
129 Returns the raw meta data for the plugin.-
130-
131 \sa metaData(), Q_PLUGIN_METADATA()-
132*/-
133-
134/*!-
135 Constructs a plugin loader with the given \a parent.-
136*/-
137QPluginLoader::QPluginLoader(QObject *parent)-
138 : QObject(parent), d(0), did_load(false)-
139{-
140}-
141-
142/*!-
143 Constructs a plugin loader with the given \a parent that will-
144 load the plugin specified by \a fileName.-
145-
146 To be loadable, the file's suffix must be a valid suffix for a-
147 loadable library in accordance with the platform, e.g. \c .so on-
148 Unix, - \c .dylib on \macos and iOS, and \c .dll on Windows. The suffix-
149 can be verified with QLibrary::isLibrary().-
150-
151 \sa setFileName()-
152*/-
153QPluginLoader::QPluginLoader(const QString &fileName, QObject *parent)-
154 : QObject(parent), d(0), did_load(false)-
155{-
156 setFileName(fileName);-
157 setLoadHints(QLibrary::PreventUnloadHint);-
158}-
159-
160/*!-
161 Destroys the QPluginLoader object.-
162-
163 Unless unload() was called explicitly, the plugin stays in memory-
164 until the application terminates.-
165-
166 \sa isLoaded(), unload()-
167*/-
168QPluginLoader::~QPluginLoader()-
169{-
170 if (d)-
171 d->release();-
172}-
173-
174/*!-
175 Returns the root component object of the plugin. The plugin is-
176 loaded if necessary. The function returns 0 if the plugin could-
177 not be loaded or if the root component object could not be-
178 instantiated.-
179-
180 If the root component object was destroyed, calling this function-
181 creates a new instance.-
182-
183 The root component, returned by this function, is not deleted when-
184 the QPluginLoader is destroyed. If you want to ensure that the root-
185 component is deleted, you should call unload() as soon you don't-
186 need to access the core component anymore. When the library is-
187 finally unloaded, the root component will automatically be deleted.-
188-
189 The component object is a QObject. Use qobject_cast() to access-
190 interfaces you are interested in.-
191-
192 \sa load()-
193*/-
194QObject *QPluginLoader::instance()-
195{-
196 if (!isLoaded() && !load())-
197 return 0;-
198 if (!d->inst && d->instance)-
199 d->inst = d->instance();-
200 return d->inst.data();-
201}-
202-
203/*!-
204 Returns the meta data for this plugin. The meta data is data specified-
205 in a json format using the Q_PLUGIN_METADATA() macro when compiling-
206 the plugin.-
207-
208 The meta data can be queried in a fast and inexpensive way without-
209 actually loading the plugin. This makes it possible to e.g. store-
210 capabilities of the plugin in there, and make the decision whether to-
211 load the plugin dependent on this meta data.-
212 */-
213QJsonObject QPluginLoader::metaData() const-
214{-
215 if (!d)-
216 return QJsonObject();-
217 return d->metaData;-
218}-
219-
220/*!-
221 Loads the plugin and returns \c true if the plugin was loaded-
222 successfully; otherwise returns \c false. Since instance() always-
223 calls this function before resolving any symbols it is not-
224 necessary to call it explicitly. In some situations you might want-
225 the plugin loaded in advance, in which case you would use this-
226 function.-
227-
228 \sa unload()-
229*/-
230bool QPluginLoader::load()-
231{-
232 if (!d || d->fileName.isEmpty())-
233 return false;-
234 if (did_load)-
235 return d->pHnd && d->instance;-
236 if (!d->isPlugin())-
237 return false;-
238 did_load = true;-
239 return d->loadPlugin();-
240}-
241-
242-
243/*!-
244 Unloads the plugin and returns \c true if the plugin could be-
245 unloaded; otherwise returns \c false.-
246-
247 This happens automatically on application termination, so you-
248 shouldn't normally need to call this function.-
249-
250 If other instances of QPluginLoader are using the same plugin, the-
251 call will fail, and unloading will only happen when every instance-
252 has called unload().-
253-
254 Don't try to delete the root component. Instead rely on-
255 that unload() will automatically delete it when needed.-
256-
257 \sa instance(), load()-
258*/-
259bool QPluginLoader::unload()-
260{-
261 if (did_load) {-
262 did_load = false;-
263 return d->unload();-
264 }-
265 if (d) // Ouch-
266 d->errorString = tr("The plugin was not loaded.");-
267 return false;-
268}-
269-
270/*!-
271 Returns \c true if the plugin is loaded; otherwise returns \c false.-
272-
273 \sa load()-
274 */-
275bool QPluginLoader::isLoaded() const-
276{-
277 return d && d->pHnd && d->instance;-
278}-
279-
280#if defined(QT_SHARED)-
281static QString locatePlugin(const QString& fileName)-
282{-
283 const bool isAbsolute = QDir::isAbsolutePath(fileName);-
284 if (isAbsolute) {
isAbsoluteDescription
TRUEevaluated 24 times by 2 tests
Evaluated by:
  • tst_QPlugin
  • tst_QPluginLoader
FALSEevaluated 3 times by 1 test
Evaluated by:
  • tst_QPluginLoader
3-24
285 QFileInfo fi(fileName);-
286 if (fi.isFile()) {
fi.isFile()Description
TRUEevaluated 23 times by 2 tests
Evaluated by:
  • tst_QPlugin
  • tst_QPluginLoader
FALSEevaluated 1 time by 1 test
Evaluated by:
  • tst_QPluginLoader
1-23
287 return fi.canonicalFilePath();
executed 23 times by 2 tests: return fi.canonicalFilePath();
Executed by:
  • tst_QPlugin
  • tst_QPluginLoader
23
288 }-
289 }
executed 1 time by 1 test: end of block
Executed by:
  • tst_QPluginLoader
1
290 QStringList prefixes = QLibraryPrivate::prefixes_sys();-
291 prefixes.prepend(QString());-
292 QStringList suffixes = QLibraryPrivate::suffixes_sys(QString());-
293 suffixes.prepend(QString());-
294-
295 // Split up "subdir/filename"-
296 const int slash = fileName.lastIndexOf(QLatin1Char('/'));-
297 const QStringRef baseName = fileName.midRef(slash + 1);-
298 const QStringRef basePath = isAbsolute ? QStringRef() : fileName.leftRef(slash + 1); // keep the '/'
isAbsoluteDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • tst_QPluginLoader
FALSEevaluated 3 times by 1 test
Evaluated by:
  • tst_QPluginLoader
1-3
299-
300 const bool debug = qt_debug_component();-
301-
302 QStringList paths;-
303 if (isAbsolute) {
isAbsoluteDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • tst_QPluginLoader
FALSEevaluated 3 times by 1 test
Evaluated by:
  • tst_QPluginLoader
1-3
304 paths.append(fileName.left(slash)); // don't include the '/'-
305 } else {
executed 1 time by 1 test: end of block
Executed by:
  • tst_QPluginLoader
1
306 paths = QCoreApplication::libraryPaths();-
307 paths.prepend(QStringLiteral(".")); // search in current dir first-
308 }
executed 3 times by 1 test: end of block
Executed by:
  • tst_QPluginLoader
3
309-
310 foreachfor (const QString &path ,: qAsConst(paths))) {-
311 foreachfor (const QString &prefix ,: qAsConst(prefixes))) {-
312 foreachfor (const QString &suffix ,: qAsConst(suffixes))) {-
313 const QString fn = path + QLatin1Char('/') + basePath + prefix + baseName + suffix;-
314 if (debug)
debugDescription
TRUEnever evaluated
FALSEevaluated 36 times by 1 test
Evaluated by:
  • tst_QPluginLoader
0-36
315 qDebug() << "Trying..." << fn;
never executed: QMessageLogger(__FILE__, 315, __PRETTY_FUNCTION__).debug() << "Trying..." << fn;
0
316 if (QFileInfo(fn).isFile())
QFileInfo(fn).isFile()Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • tst_QPluginLoader
FALSEevaluated 34 times by 1 test
Evaluated by:
  • tst_QPluginLoader
2-34
317 return fn;
executed 2 times by 1 test: return fn;
Executed by:
  • tst_QPluginLoader
2
318 }
executed 34 times by 1 test: end of block
Executed by:
  • tst_QPluginLoader
34
319 }
executed 16 times by 1 test: end of block
Executed by:
  • tst_QPluginLoader
16
320 }
executed 7 times by 1 test: end of block
Executed by:
  • tst_QPluginLoader
7
321 if (debug)
debugDescription
TRUEnever evaluated
FALSEevaluated 2 times by 1 test
Evaluated by:
  • tst_QPluginLoader
0-2
322 qDebug() << fileName << "not found";
never executed: QMessageLogger(__FILE__, 322, __PRETTY_FUNCTION__).debug() << fileName << "not found";
0
323 return QString();
executed 2 times by 1 test: return QString();
Executed by:
  • tst_QPluginLoader
2
324}-
325#endif-
326-
327/*!-
328 \property QPluginLoader::fileName-
329 \brief the file name of the plugin-
330-
331 We recommend omitting the file's suffix in the file name, since-
332 QPluginLoader will automatically look for the file with the appropriate-
333 suffix (see QLibrary::isLibrary()).-
334-
335 When loading the plugin, QPluginLoader searches in the current directory and-
336 in all plugin locations specified by QCoreApplication::libraryPaths(),-
337 unless the file name has an absolute path. After loading the plugin-
338 successfully, fileName() returns the fully-qualified file name of-
339 the plugin, including the full path to the plugin if one was given-
340 in the constructor or passed to setFileName().-
341-
342 If the file name does not exist, it will not be set. This property-
343 will then contain an empty string.-
344-
345 By default, this property contains an empty string.-
346-
347 \sa load()-
348*/-
349void QPluginLoader::setFileName(const QString &fileName)-
350{-
351#if defined(QT_SHARED)-
352 QLibrary::LoadHints lh = QLibrary::PreventUnloadHint;-
353 if (d) {-
354 lh = d->loadHints();-
355 d->release();-
356 d = 0;-
357 did_load = false;-
358 }-
359-
360 const QString fn = locatePlugin(fileName);-
361-
362 d = QLibraryPrivate::findOrCreate(fn, QString(), lh);-
363 if (!fn.isEmpty())-
364 d->updatePluginState();-
365-
366#else-
367 if (qt_debug_component()) {-
368 qWarning("Cannot load %s into a statically linked Qt library.",-
369 (const char*)QFile::encodeName(fileName));-
370 }-
371 Q_UNUSED(fileName);-
372#endif-
373}-
374-
375QString QPluginLoader::fileName() const-
376{-
377 if (d)-
378 return d->fileName;-
379 return QString();-
380}-
381-
382/*!-
383 \since 4.2-
384-
385 Returns a text string with the description of the last error that occurred.-
386*/-
387QString QPluginLoader::errorString() const-
388{-
389 return (!d || d->errorString.isEmpty()) ? tr("Unknown error") : d->errorString;-
390}-
391-
typedef QVector<QStaticPlugin> StaticPluginList;
Q_GLOBAL_STATIC(StaticPluginList, staticPluginList)/*! \since 4.4
393-
394 \property QPluginLoader::loadHints-
395 \brief Give the load() function some hints on how it should behave.-
396-
397 You can give hints on how the symbols in the plugin are-
398 resolved. By default since Qt 5.7, QLibrary::PreventUnloadHint is set.-
399-
400 See the documentation of QLibrary::loadHints for a complete-
401 description of how this property works.-
402-
403 \sa QLibrary::loadHints-
404*/-
405-
406void QPluginLoader::setLoadHints(QLibrary::LoadHints loadHints)-
407{-
408 if (!d) {-
409 d = QLibraryPrivate::findOrCreate(QString()); // ugly, but we need a d-ptr-
410 d->errorString.clear();-
411 }-
412 d->setLoadHints(loadHints);-
413}-
414-
415QLibrary::LoadHints QPluginLoader::loadHints() const-
416{-
417 return d ? d->loadHints() : QLibrary::LoadHints();-
418}-
419-
420#endif // QT_NO_LIBRARY-
421-
422typedef QVector<QStaticPlugin> StaticPluginList;-
423Q_GLOBAL_STATIC(StaticPluginList, staticPluginList)-
424-
425/*!-
426 \relates QPluginLoader-
427 \since 5.0-
428-
429 Registers the \a plugin specified with the plugin loader, and is used-
430 by Q_IMPORT_PLUGIN().-
431*/-
432void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin plugin)-
433{-
434 staticPluginList()->append(plugin);-
435}-
436-
437/*!-
438 Returns a list of static plugin instances (root components) held-
439 by the plugin loader.-
440 \sa staticPlugins()-
441*/-
442QObjectList QPluginLoader::staticInstances()-
443{-
444 QObjectList instances;-
445 const StaticPluginList *plugins = staticPluginList();-
446 if (plugins) {-
447 const int numPlugins = plugins->size();-
448 instances.reserve(numPlugins);-
449 for (int i = 0; i < numPlugins; ++i)-
450 instances += plugins->at(i).instance();-
451 }-
452 return instances;-
453}-
454-
455/*!-
456 Returns a list of QStaticPlugins held by the plugin-
457 loader. The function is similar to \l staticInstances()-
458 with the addition that a QStaticPlugin also contains-
459 meta data information.-
460 \sa staticInstances()-
461*/-
462QVector<QStaticPlugin> QPluginLoader::staticPlugins()-
463{-
464 StaticPluginList *plugins = staticPluginList();-
465 if (plugins)-
466 return *plugins;-
467 return QVector<QStaticPlugin>();-
468}-
469-
470/*!-
471 Returns a the meta data for the plugin as a QJsonObject.-
472-
473 \sa rawMetaData()-
474*/-
475QJsonObject QStaticPlugin::metaData() const-
476{-
477 return QLibraryPrivate::fromRawMetaDataqJsonFromRawLibraryMetaData(rawMetaData()).object();
executed 26 times by 1 test: return qJsonFromRawLibraryMetaData(rawMetaData()).object();
Executed by:
  • tst_QGuiApplication
26
478}-
479-
480QT_END_NAMESPACE-
481-
#endif
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9