2 votes

Cadre de plugin en C++ avec

Je conçois (brainstorming) un cadre de plugin C++ pour une architecture extensible. Chaque plugin enregistre une interface, qui est implémentée par le plugin lui-même. Un tel framework peut fonctionner sur des appareils embarqués relativement performants (par exemple Atom/ARM) donc je peux utiliser STL et Boost.

Pour le moment, j'ai réussi à écrire un framework similaire, dans lequel les interfaces sont connues à l'avance et les plugins (chargés à partir de bibliothèques dynamiques) enregistrent les objets les implémentant. Ces objets sont instanciés au besoin par leurs méthodes de fabrique, et les méthodes sont appelées correctement.

Maintenant, je veux le rendre plus flexible, en permettant aux plugins d'enregistrer de nouvelles interfaces (et pas seulement d'implémenter celles déjà existantes), étendant ainsi l'API disponible aux utilisateurs du framework.

J'ai pensé à utiliser un std::map, qui est également mentionné dans plusieurs articles et réponses de stackoverflow que j'ai lus. Malheureusement, cela ne semble pas couvrir le cas des différentes interfaces de méthode.

J'ai l'impression que cela pourrait avoir quelque chose à voir avec la méta-programmation des templates, ou des traits peut-être, mais je n'arrive pas à comprendre comment cela devrait fonctionner exactement. Est-ce que quelqu'un peut m'aider?

2voto

gbjbaanb Points 31045

Essayez de regarder XPCOM qui résout ces problèmes pour vous - en réimplémentant en quelque sorte COM.

Vous avez le problème de ne pas savoir quelle interface le plugin fournit à votre application, donc vous avez besoin d'un moyen pour que le développeur y accède, sans que le compilateur ne sache ce que c'est (bien que, si vous fournissez un fichier d'en-tête, alors tout à coup vous savez ce que c'est et vous pouvez le compiler sans avoir besoin de la fantaisie des plugins avec interface inconnue)

donc, vous allez devoir compter sur le déterminisme de l'interface au moment de l'exécution, ce qui vous oblige plus ou moins à définir l'interface d'une manière telle que le framework puisse appeler des méthodes arbitraires dessus, et je pense que la seule façon réaliste que vous pouvez le faire est de définir chaque interface comme un ensemble de pointeurs de fonction qui sont chargés individuellement puis stockés dans des données pour que l'utilisateur puisse les appeler. Et cela signifie en gros une carte des pointeurs de fonctions vers des noms. Cela signifie également que vous ne pouvez utiliser de facilités de compilation (telles que la surcharge) qu'en rendant les noms de fonction uniques. Le compilateur le fait pour vous en 'mangeant' tous les noms de fonctions pour en faire des noms uniques et codés.

Traits de types vous aideront à envelopper vos fonctions importées dans votre framework, afin que vous puissiez les inspecter et créer des classes qui fonctionnent avec n'importe quel type importé, mais cela ne résoudra pas le principal problème d'importer des fonctions arbitraires.

Peut-être une approche que vous voudrez lire est Métaclasses et Réflexion par Vollmann. Cela a été mentionné par l'organe de normalisation C++, bien que je ne sache pas s'il fera partie d'une future spécification. Alternativement, vous pouvez consulter Boost.Extension

0voto

BlueWanderer Points 1218

Peut-être la première chose que vous devez vérifier est COM.

0voto

n.m. Points 30344

Tout ce qui peut être fait avec des modèles peut également être fait sans, bien que peut-être de manière beaucoup moins pratique, en écrivant "à la main" des "instances de modèles".

Si votre framework a été compilé sans avoir vu une déclaration de class MyNewShinyInterface, il ne peut pas stocker des pointeurs de type MyNewShinyInterface *, et ne peut pas les renvoyer aux utilisateurs du framework. Aucune magie de modèle ne peut changer cela. Le framework ne peut stocker et passer autour que des pointeurs vers une classe de base. Les utilisateurs devront faire un dynamic_cast pour récupérer le pointeur correctement typé.

Il en va de même pour les pointeurs de fonction, sauf que les fonctions n'ont pas de classe de base et il faudra faire le reinterpret_cast propice aux erreurs pour récupérer le bon type. (C'est juste une autre raison de préférer les objets appropriés aux pointeurs de fonction.)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X