Skip to content
This repository was archived by the owner on Mar 4, 2023. It is now read-only.

Commit 8929b83

Browse files
committed
added static plugin support and macros
1 parent 6bb98d0 commit 8929b83

File tree

3 files changed

+133
-39
lines changed

3 files changed

+133
-39
lines changed

qpluginfactory.cpp

Lines changed: 111 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,32 @@
77

88
extern bool __qpluginfactory_is_debug();
99

10+
class StaticPluginInfo : public QPluginFactoryBase::PluginInfo
11+
{
12+
public:
13+
StaticPluginInfo(const QStaticPlugin &plugin);
14+
15+
QJsonObject metaData() const override;
16+
QObject *instance() override;
17+
18+
private:
19+
QStaticPlugin _plugin;
20+
};
21+
22+
class DynamicPluginInfo : public QPluginFactoryBase::PluginInfo
23+
{
24+
public:
25+
DynamicPluginInfo(QScopedPointer<QPluginLoader, QScopedPointerDeleteLater> &loader);
26+
27+
QJsonObject metaData() const override;
28+
QObject *instance() override;
29+
30+
private:
31+
QScopedPointer<QPluginLoader, QScopedPointerDeleteLater> _loader;
32+
};
33+
34+
35+
1036
QPluginFactoryBase::QPluginFactoryBase(const QString &pluginType, QObject *parent) :
1137
QPluginFactoryBase(pluginType, QByteArray(), parent)
1238
{}
@@ -17,8 +43,9 @@ QPluginFactoryBase::QPluginFactoryBase(const QString &pluginType, const QByteArr
1743
_pluginIid(pluginIid),
1844
_extraDirs(),
1945
_loaderMutex(),
20-
_loaders()
46+
_plugins()
2147
{
48+
//setup dynamic plugins
2249
reloadPlugins();
2350
}
2451

@@ -35,28 +62,26 @@ void QPluginFactoryBase::addSearchDir(const QDir &dir, bool isTopLevel)
3562
QStringList QPluginFactoryBase::allKeys() const
3663
{
3764
QMutexLocker _(&_loaderMutex);
38-
return _loaders.keys();
65+
return _plugins.keys();
3966
}
4067

4168
QJsonObject QPluginFactoryBase::metaData(const QString &key) const
4269
{
4370
QMutexLocker _(&_loaderMutex);
44-
auto loader = _loaders.value(key);
45-
if(loader)
46-
return loader->metaData()[QStringLiteral("MetaData")].toObject();
71+
auto info = _plugins.value(key);
72+
if(info)
73+
return info->metaData()[QStringLiteral("MetaData")].toObject();
4774
else
4875
return {};
4976
}
5077

5178
QObject *QPluginFactoryBase::plugin(const QString &key) const
5279
{
5380
QMutexLocker _(&_loaderMutex);
54-
auto loader = _loaders.value(key);
55-
if(loader) {
56-
if(!loader->isLoaded() && !loader->load())
57-
throw QPluginLoadException(loader);
58-
return loader->instance();
59-
} else
81+
auto info = _plugins.value(key);
82+
if(info)
83+
return info->instance();
84+
else
6085
return nullptr;
6186
}
6287

@@ -81,7 +106,7 @@ void QPluginFactoryBase::reloadPlugins()
81106
QMutexLocker _(&_loaderMutex);
82107

83108
//find the plugin dir
84-
auto oldKeys = _loaders.keys();
109+
auto oldKeys = _plugins.keys();
85110

86111
QList<QDir> allDirs;
87112
//first: dirs in path
@@ -107,45 +132,61 @@ void QPluginFactoryBase::reloadPlugins()
107132
if(pluginMainDir.cd(_pluginType))
108133
allDirs.append(pluginMainDir);
109134

135+
//setup dynamic plugins
110136
foreach(auto pluginDir, allDirs) {
111137
foreach(auto info, pluginDir.entryInfoList(QDir::Files | QDir::Readable | QDir::Executable | QDir::NoDotAndDotDot)) {
112-
QSharedPointer<QPluginLoader> plugin(new QPluginLoader(info.absoluteFilePath()), &QObject::deleteLater);
113-
auto metaData = plugin->metaData();
114-
115-
//skip non-matching types
116-
if(metaData[QStringLiteral("debug")].toBool() != __qpluginfactory_is_debug())
117-
continue;
118-
119-
auto iid = plugin->metaData().value(QStringLiteral("IID")).toString().toUtf8();
120-
if(!_pluginIid.isNull() && iid != _pluginIid) {
121-
qWarning().noquote() << "File" << plugin->fileName() << "is no plugin of type" << _pluginIid;
122-
continue;
123-
}
124-
125-
auto data = metaData[QStringLiteral("MetaData")].toObject();
126-
auto keys = data[QStringLiteral("Keys")].toArray();
127-
if(keys.isEmpty()) {
128-
qWarning().noquote() << "Plugin" << plugin->fileName() << "is does not provide any Keys";
129-
continue;
130-
}
131-
138+
QScopedPointer<QPluginLoader, QScopedPointerDeleteLater> loader(new QPluginLoader(info.absoluteFilePath()));
139+
auto metaData = loader->metaData();
140+
auto keys = checkMeta(metaData, loader->fileName());
132141
foreach(auto key, keys) {
133142
auto k = key.toString();
134-
if(!_loaders.contains(k))
135-
_loaders.insert(k, plugin);
143+
if(!_plugins.contains(k))
144+
_plugins.insert(k, QSharedPointer<DynamicPluginInfo>::create(loader));
136145
oldKeys.removeOne(k);
137146
}
147+
}
148+
}
138149

150+
//setup static plugins
151+
foreach(auto info, QPluginLoader::staticPlugins()) {
152+
auto keys = checkMeta(info.metaData(), QString());
153+
foreach(auto key, keys) {
154+
auto k = key.toString();
155+
if(!_plugins.contains(k))
156+
_plugins.insert(k, QSharedPointer<StaticPluginInfo>::create(info));
157+
oldKeys.removeOne(k);
139158
}
140159
}
141160

161+
//remove old, now unused plugins
142162
foreach(auto key, oldKeys)
143-
_loaders.remove(key);
163+
_plugins.remove(key);
144164
}
145165

166+
QJsonArray QPluginFactoryBase::checkMeta(const QJsonObject &metaData, const QString &filename) const
167+
{
168+
if(metaData[QStringLiteral("debug")].toBool() != __qpluginfactory_is_debug())
169+
return {};
146170

171+
auto iid = metaData.value(QStringLiteral("IID")).toString().toUtf8();
172+
if(!_pluginIid.isNull() && iid != _pluginIid) {
173+
qWarning().noquote() << "File" << filename << "is no plugin of type" << _pluginIid;
174+
return {};
175+
}
147176

148-
QPluginLoadException::QPluginLoadException(QSharedPointer<QPluginLoader> loader) :
177+
auto data = metaData[QStringLiteral("MetaData")].toObject();
178+
auto keys = data[QStringLiteral("Keys")].toArray();
179+
if(keys.isEmpty()) {
180+
qWarning().noquote() << "Plugin" << filename << "is does not provide any Keys";
181+
return {};
182+
}
183+
184+
return keys;
185+
}
186+
187+
188+
189+
QPluginLoadException::QPluginLoadException(QPluginLoader *loader) :
149190
QPluginLoadException(QStringLiteral("Failed to load plugin \"%1\" with error: %2")
150191
.arg(loader->fileName())
151192
.arg(loader->errorString())
@@ -171,3 +212,37 @@ QPluginLoadException::QPluginLoadException(const QByteArray &error) :
171212
QException(),
172213
_what(error)
173214
{}
215+
216+
217+
218+
StaticPluginInfo::StaticPluginInfo(const QStaticPlugin &plugin) :
219+
_plugin(plugin)
220+
{}
221+
222+
QJsonObject StaticPluginInfo::metaData() const
223+
{
224+
return _plugin.metaData();
225+
}
226+
227+
QObject *StaticPluginInfo::instance()
228+
{
229+
return _plugin.instance();
230+
}
231+
232+
DynamicPluginInfo::DynamicPluginInfo(QScopedPointer<QPluginLoader, QScopedPointerDeleteLater> &loader) :
233+
_loader()
234+
{
235+
_loader.swap(loader);
236+
}
237+
238+
QJsonObject DynamicPluginInfo::metaData() const
239+
{
240+
return _loader->metaData();
241+
}
242+
243+
QObject *DynamicPluginInfo::instance()
244+
{
245+
if(!_loader->isLoaded() && !_loader->load())
246+
throw QPluginLoadException(_loader.data());
247+
return _loader->instance();
248+
}

qpluginfactory.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
class QPluginLoadException : public QException
1111
{
1212
public:
13-
QPluginLoadException(QSharedPointer<QPluginLoader> loader);
13+
QPluginLoadException(QPluginLoader *loader);
1414

1515
const char *what() const noexcept override;
1616
void raise() const override;
@@ -29,6 +29,13 @@ class QPluginFactoryBase : public QObject
2929
Q_PROPERTY(QByteArray pluginIid READ pluginIid WRITE setPluginIid)
3030

3131
public:
32+
class PluginInfo {
33+
public:
34+
virtual inline ~PluginInfo() = default;
35+
virtual QJsonObject metaData() const = 0;
36+
virtual QObject *instance() = 0;
37+
};
38+
3239
QPluginFactoryBase(const QString &pluginType, QObject *parent = nullptr);
3340
QPluginFactoryBase(const QString &pluginType, const QByteArray &pluginIid, QObject *parent = nullptr);
3441

@@ -52,7 +59,9 @@ public slots:
5259
QList<QDir> _extraDirs;
5360

5461
mutable QMutex _loaderMutex;
55-
QHash<QString, QSharedPointer<QPluginLoader>> _loaders;
62+
QHash<QString, QSharedPointer<PluginInfo>> _plugins;
63+
64+
QJsonArray checkMeta(const QJsonObject &metaData, const QString &filename) const;
5665
};
5766

5867
template <typename TPlugin>
@@ -118,4 +127,14 @@ TObject *QPluginObjectFactory<TPlugin, TObject>::createInstance(const QString &k
118127
return nullptr;
119128
}
120129

130+
#define Q_GLOBAL_PLUGIN_FACTORY(PluginType, pluginKey, instName) namespace { \
131+
typedef QPluginFactory<PluginType> __QGPF_ ## PluginType ## _Factory; \
132+
Q_GLOBAL_STATIC_WITH_ARGS(__QGPF_ ## PluginType ## _Factory, instName, (QLatin1String(pluginKey))) \
133+
}
134+
135+
#define Q_GLOBAL_PLUGIN_OBJECT_FACTORY(PluginType, ObjectType, pluginKey, instName) namespace { \
136+
typedef QPluginObjectFactory<PluginType, ObjectType> __QGPF_ ## PluginType ## _Factory; \
137+
Q_GLOBAL_STATIC_WITH_ARGS(__QGPF_ ## PluginType ## _Factory, instName, (QLatin1String(pluginKey))) \
138+
}
139+
121140
#endif // QPLUGINFACTORY_H

qpm.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
},
1616
"version": {
1717
"fingerprint": "",
18-
"label": "1.0.1",
18+
"label": "1.1.0",
1919
"revision": ""
2020
},
2121
"webpage": "https://github.com/Skycoder42/QPluginFactory"

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy