IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Qt Discussion :

Plugins d'application. Question de design et méthodologie


Sujet :

Qt

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 8
    Points : 7
    Points
    7
    Par défaut Plugins d'application. Question de design et méthodologie
    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:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    virtual QMenu* menu() const = 0;
    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.

    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:

    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);
    }
    Et du coté du PluginHandler:

    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);
    }
    Maintenant ce qui cloche dans mon approche est le fait que PluginHandler est partagé à la fois par l'application et aussi par les plugins.
    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);

  2. #2
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 8
    Points : 7
    Points
    7
    Par défaut
    Encore moi, bon, j'ai résolu mon problème

    Pour ceux que ça intéresse, je ne passe plus par la création de librairies statiques.
    Je me contente d'ajouter pluginhandler.h/.cpp dans phase de compilation du plugin.
    A vrai dire, j'avais déjà tenté de faire ça (ainsi que d'importer les .o), mais pour je ne sais quelle raison, ça n'avait pas fonctionné (et oui, j'avais bien lancé les qmake qui vont bien..)

    Néanmoins, je continue de penser que l'utilisation de librairies statiques est censé être la solution la plus propre pour mon approche... enfin bon, on va pas trop chipoter

    -resolved-

    Edit: je suis toujours intéressé de savoir comment vous gérez vos plugins dans vos applications

  3. #3
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Salut et bienvenu sur le forum,

    Citation Envoyé par xadrier Voir le message
    Je me contente d'ajouter pluginhandler.h/.cpp dans phase de compilation du plugin.

    Néanmoins, je continue de penser que l'utilisation de librairies statiques est censé être la solution la plus propre pour mon approche... enfin bon, on va pas trop chipoter
    je ne suis pas un expert en plug in mais à mon avis ce n'est pas optimale.
    Tu te retrouve avec des doublon de code.

    A mon avis le plus propre est de créé une dll partagé entre l'application et les plug in représentant PluginHandler

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 8
    Points : 7
    Points
    7
    Par défaut
    Citation Envoyé par Mongaulois Voir le message
    A mon avis le plus propre est de créé une dll partagé entre l'application et les plug in représentant PluginHandler
    Effectivement ça serait la solution la plus idéale en terme de versioning et d'espace.
    Je ne suis pas du tout familier des librairies partagées dans un cadre cross platform, mais je vais essayer de voir ce que je peux faire

    Merci

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 8
    Points : 7
    Points
    7
    Par défaut
    Encore moi.
    Je poste ici mon avancement car ça peut toujours intéresser du monde.

    Je pense avoir une solution viable maintenant, dans l'esprit de ce que Mongaulois a suggéré deux posts plus haut (merci).

    Le but du jeu est d'avoir un "layer" entre l'application principale et ses plugins. Ce layer, ici nommé PluginHandler, permet un faible couplage entre l'app et les plugins. Les plugins ont potentiellement une très grande liberté d'action sans pour autant devoir modifier l'application ni sans trop exposer son architecture interne aux plugins. De plus, l'interface des plugins n'a pas besoins de changer dès qu'on veut ajouter une nouvelle possibilité. On se contente d'adapter le PluginHandler qui est dorénavant une librairie partagée et donc découplée et facilement "upgradable".
    Rien n'a changé par rapport à mon premier post niveau utilisation. Voici la forme des fichier pro utilisé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
     
    /* pluginhandler.pro */
    TARGET = PluginHandler
    TEMPLATE = lib
    DEFINES += PLUGINHANDLER_LIBRARY
    SOURCES += pluginhandler.cpp
    HEADERS += pluginhandler.h
     
     
     
    /* pluginhandler.h */
    #if defined(PLUGINHANDLER_LIBRARY)
    #  define PLUGINHANDLERSHARED_EXPORT Q_DECL_EXPORT
    #else
    #  define PLUGINHANDLERSHARED_EXPORT Q_DECL_IMPORT
    #endif
     
    class PLUGINHANDLERSHARED_EXPORT PluginHandler : public QObject
    {
      Q_OBJECT;
      // members, signals, slots etc
      // ..
    };
     
     
     
    /* main application pro file */
    TEMPLATE = app
    LIBS += -lPluginHandler
    ...
     
     
    /* testplugin.pro */
    TARGET = TestPlugin
    TEMPLATE = lib
    CONFIG += plugin
    LIBS += -lPluginHandler
    SOURCES += testplugin.cpp
    HEADERS += testplugin.h
    L'application charge la shared lib PluginHandler de manière statique au démarrage. Nul besoins de manipuler QLibrary ou QPluginLoader. En parallèle on continue d'utiliser les plugins dynamiques comme indiqué dans la doc Qt.
    Les signaux/slots circulent à travers les 3 composants. C'est super cool

    Voilà.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Visual studio 2005] Web Application -> pas de Designer.cs
    Par joujoukinder dans le forum Visual Studio
    Réponses: 5
    Dernier message: 14/03/2008, 19h01
  2. Plugins pour applications win 32
    Par Targan dans le forum Langage
    Réponses: 1
    Dernier message: 18/12/2007, 15h40
  3. Question de design
    Par Dohmaker dans le forum ASP.NET
    Réponses: 3
    Dernier message: 24/09/2007, 20h29
  4. Question de design?
    Par Jayceblaster dans le forum Delphi
    Réponses: 9
    Dernier message: 06/06/2006, 20h38
  5. [Struts] question de design
    Par mlequim dans le forum Struts 1
    Réponses: 4
    Dernier message: 26/10/2005, 13h27

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo