2008-12-09 4 views
12

J'ai donc une application basée sur l'API QT qui utilise le système QPlugin. C'est assez simple à utiliser, vous définissez une classe qui hérite d'une interface et lorsque le plugin est chargé, vous obtenez une instance de cette classe. À la fin, il se résumera à dlopen/dlsym ou LoadLibrary/GetProcAddress, tout ce qui est approprié pour le système d'exploitation. Je n'ai aucun problème ici tout fonctionne comme prévu.Conception de l'API du plugin

Donc, sur le problème. Il y a un lot de fonctionnalité qui implique un plugin ayant besoin de se référer aux données/fonctions fournies par l'application principale. Par exemple, mon application a une interface graphique, j'ai donc dans mon application une fonction "plugin::v1::gui" qui renvoie un QWidget *. Si je veux qu'un plugin soit capable d'ajouter des choses à mon interface utilisateur, ou même de faire de sa boîte de dialogue un enfant de mon interface utilisateur, il aura besoin d'un pointeur.

J'ai commencé le développement sous Linux et j'ai rapidement rencontré le fait que par défaut le chargeur ne remplissait pas les symboles non résolus dans les objets partagés avec ceux de l'application qui le chargeait. Pas de problème, solution facile. ajoutez "-rdynamic" à mes drapeaux et continuez. Chose fonctionne bien.

Maintenant, je l'ai découvert qu'il ne semble pas être un équivalent sur Windows :(. Quel est donc une bonne solution?

Jusqu'à présent, le meilleur que je suis venu avec une structure est d'avoir I remplissez dans mon application principale qui a des pointeurs vers chaque objet/fonction dont un plugin pourrait se soucier.Puis passer cela à la fonction "init()" du plugin et maintenant il a des pointeurs appropriés à tout, mais c'est une solution ennuyante car maintenant je dois faire changements dans plusieurs endroits chaque fois que j'ajoute quelque chose

Existe-t-il une meilleure solution? Comment la communauté SO a-t-elle traité cela?

Répondre

4

Créez un ensemble d'interfaces pour les objets d'interaction principaux qui seront exposés par votre application et construisez-les dans une lib/dll qui leur est propre et implémentez ces interfaces dans les classes de votre application, selon le cas. La bibliothèque doit également inclure une interface de plugin avec peut-être juste une méthode "initialize" que l'objet plugin implémentera. L'application et le plugin vont évidemment se lier à cette DLL et une fois que le plugin est chargé par l'application, l'application doit appeler la méthode initialize du plugin qui aura des paramètres pour accepter tous les objets nécessaires pour contrôler l'application.

Une manière populaire de simplifier consiste à implémenter une hiérarchie similaire au DOM dans votre application afin que le plugin puisse accéder à tous les objets pertinents de votre application à partir d'un objet racine.

+0

Voici un bon article qui explique en détail comment accomplir des plugins de cette manière: http://www.nuclex.org/articles/building-a-better-plugin-architecture#comment-738 – joshperry

0

Créez un objet de registre transmis au plug-in dans la fonction d'initialisation qui contient un dictionnaire de composants exposés. Ensuite, autorisez le plugin à demander un pointeur sur les composants par nom de chaîne ou autre identifiant de ce registre. Il sacrifie la sécurité de type à la compilation pour une interface stable.

Il y a aussi des solutions plus lourdes poids comme CORBA ...

+0

C'est la plupart du temps * identique * à ma phrase "jusqu'ici le meilleur que j'ai trouvé ...". seule la vraie différence est de savoir si elles demandent par un élément de structure ou par un passage de chaîne. Je vais prendre la structure à cause de la sécurité du type. –

+0

Je ne peux pas imaginer d'autre solution au problème. Qu'avez-vous pensé d'Evan? –

+0

Malheureusement, jusqu'à présent, je n'ai rien trouvé de vraiment supérieur. Linux -rdynamic aurait vraiment été agréable à suivre. J'ai commencé à convertir mon API de plugin en une structure passée, et c'est vraiment très long de faire les choses correctement. –

0

Vous avez fait cela d'une manière relativement bonne. Les classes d'assistance sont souvent le moyen idéal pour (seulement) INSÉRER une nouvelle fonctionnalité. Si vous concevez votre logiciel, vous devez mentionner que tous les plugins ne doivent pas avoir accès à votre structure administrative. Il devrait donc y avoir des différences dans la conception des plugins.

Une possibilité: Créez des classes abstraites dont vous héritez, avec des fonctionnalités pour définir les pointeurs requis sur Widgets.

Autre possibilité: Élargissez vos principaux (parents) des classes avec des fonctions de getParent() getMainWidget(), getParent() getConfigWidget() ....


Si elle est seulement de façon dynamique.. chargement de votre interface utilisateur UIs-Plugin sans utiliser des pointeurs, vous pouvez le faire que sur cette page décrit: http://dolzhenko.blogspot.com/2008/10/qt4-dynamic-loading-ui-from-other-ui_07.html

il est fait avec ui-Files vous pouvez accéder sur votre principale config-Files ou autre.

Questions connexes