plugin/qpluginloader.cpp

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

Generated by Squish Coco Non-Commercial