Pour une application avec Qt (projet perso), j'essaye de mettre en place un système de plugin. J'ai suivi la doc, ça fonctionne bien. Néanmoins, j'aimerai donner plus de souplesse et de possibilités à mes plugins tout en ayant une interface de plugin très simplifiée.
C'est à dire qu'au lieu de déclarer N fontions virtuelles dans l'interface, je n'en déclare qu'une seule qui reçoit en paramètre un pointeur sur un "plugin handler" qui lui fait la jonction entre le plugin et l'application.
Pour vous donner un exemple, imaginons que le plugin veuille ajouter un menu à l'application. Le truc simple et qui fonctionne est d'avoir ce genre de fonction dans l'interface du plugin:
Puis l'application après avoir chargé le plugin va appeler cette fonction et "ajouter" elle-même le menu qui sera retourné par le plugin.
Code : Sélectionner tout - Visualiser dans une fenêtre à part virtual QMenu* menu() const = 0;
Maintenant ce que je cherche à faire est de donner au "plugin handler" le rôle d'ajouter lui-même le menu à l'application.
Lorsque l'appli démarre, une instance de PluginHandler est créée. Celle-ci garde un pointeur sur l'application principale.
Une fois le plugin chargé, l'application lui passe le PluginHandler et c'est le plugin qui décide s'il veut ajouter le menu ou non.
Un exemple:
Et du coté du PluginHandler:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 // nous sommes ici dans le plugin void TestPlugin::init(PluginHandler* handler) { // QMenu* menu = new QMenu...; handler->setMenu(menu); }
Maintenant ce qui cloche dans mon approche est le fait que PluginHandler est partagé à la fois par l'application et aussi par les plugins.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 void PluginHandler::setMenu(QMenu* menu) { // mainWindow_ est un pointeur sur l'application principale mainWindow_->menuBar()->addMenu(menu); }
Ca ne pose pas de problème quand je compile l'application seule.
En revanche, quand je compile un plugin, le linker (gcc win32) me dit qu'il y a des undefined references concernant le Pluginhandler.
J'ai donc essayé de compiler l'appli principale en tant que static library et la lier lors de la compilation du plugin.
Après quelques tentatives, j'arrive à tout compiler mais l'application principale n'est plus en mesure de loader mon plugin...
pluginLoader.errorString() retourne "cannot load library TestPlugin.dll".
Alors j'en viens quand même à ma question:
Que feriez-vous dans un pareil cas ?
Dois-je essayer de découpler le PluginHandler de l'application principale (essayer de ne mettre que lui dans une librarie statique qui serait linkée lors de la compilation de l'appli et des plugins ?)
Ferais-je fausse route ?
Comment gérez-vous vos plugins d'applications ?
Merci
Juste pour info, voici mes headers simplifiés:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 /* mainwindow.h */ class MainWindow : public QMainWindow { Q_OBJECT; // un des membres est de ce type: PluginHandler* pluginHandler_; // gui, slots etc.. }; /* pluginhandler.h */ class PluginHandler : public QObject { Q_OBJECT; public: // prend un MainWindow* en parametre PluginHandler(MainWindow* mainWindow); // diverses methodes qui utilisent mainWindow_* // ces methodes sont destinées à etre callé du plugin void setMenu(QMenu* menu); // pointeur sur la main window MainWindow* mainWindow_; }; /* pluginface.h (plugin interface) */ class PluginFace { public: virtual ~PluginFace() {} // passe un PluginHandler* au plugin virtual void init(PluginHandler* handler) = 0; }; Q_DECLARE_INTERFACE(PluginFace, "foo.PluginFace/1.0"); /* testplugin.h (implemente l'interface) */ class TestPlugin : public QObject, PluginFace { Q_OBJECT; Q_INTERFACES(PluginFace); public: void init(PluginHandler* handler); PluginHandler* handler_; }; // dans testplugin.cpp, présence de: //Q_EXPORT_PLUGIN2(testplugin, TestPlugin);
Partager