III. Seconde partie▲
Ces applications fonctionnent probablement correctement avec vos plugins dédiés. Les problèmes surviennent lorsque vous essayez de mélanger des plugins écrits par vos utilisateurs compilés à l'aide de compilateurs différents (cela peut fonctionner) ou bien pour des systèmes d'exploitation différents (cela ne peut pas fonctionner !).
Lorsque nous concevons de véritables applications, nous ne pouvons utiliser cette approche que très rarement. Nous n'avons la garantie que les plugins, issus de bibliothèques partagées liées dynamiquement, fonctionneront comme ils le doivent que si nous les compilons avec la même version de compilateur et de système d'exploitation que ceux utilisés pour produire les fichiers binaires des applications. La deuxième restriction avec l'approche que j'ai présentée dans les deux derniers articles (introduction et première partie) est que ces programmes fonctionneront seulement avec certains systèmes compatibles UNIX. Si nous avons besoin d'applications modulaires portables, nous devons utiliser des bibliothèques dédiées qui proposent des interfaces portables. Un exemple de ce type de bibliothèques est Poco::SharedLibrary. J'écrirai quelque chose là-dessus plus tard.
III-A. Existe-t-il une bonne solution ?▲
Les problèmes d'écriture de bibliothèques partagées portables en C++ ont sans doute conduit au développement de bibliothèques qui transposent les applications Python au C++ ou des interpréteurs pour des langages comme JavaScript. Grâce à eux, nous pouvons écrire des extensions dans un langage de plus haut niveau qui est, par nature, portable et qui pourront être utilisées par C++.
Les meilleurs exemples d'utilisation de telles solutions sont les navigateurs web provenant de Mozilla et Google. Tous les deux possèdent une grande et respectable collection d'extensions écrites par des développeurs du monde entier. Les plugins de Firefox et de Chrome sont écrits en JavaScript. Les navigateurs d'aujourd'hui ont toujours un moteur JavaScript, et donc l'utiliser pour un besoin supplémentaire n'est pas un problème.
Mozilla a créé un moteur d'analyse syntaxique JavaScript open source appelé SpiderMonkey. Google propose également leur solution appelée V8. JavaScript semble être un bon moyen d'implémentation d'une interface de plugins.
La bibliothèque Boost::Python est un autre grand outil qui fournit des outils permettant d'utiliser du code C++ dans un programme Python et inversement. Bien sûr, parfois, nous devons écrire un code très rapide et très efficace. Dans ce cas JavaScript ou même Python ne sont pas assez bons. Nous devons toujours chercher quelle est la solution optimale pour nous.
III-B. Problèmes avec les plugins C++▲
Je vous ai dit que les plugins C++ pouvaient poser problème lorsque nous utilisons des compilateurs différents pour transformer le code en fichier binaire. Les principales causes de ce problème viennent des différences dans l'interface binaire de l'application (ABI) qui peuvent être différentes pour le même code source compilé à l'aide de compilateurs différents voire entre différentes versions d'un même compilateur. On peut remarquer ce problème avec des systèmes d'exploitation à la sauce UNIX. Un format souvent utilisé, appelé « Executable and Linkable Format » (ELF), devient de plus en plus populaire ce qui pourrait résulter en une meilleure compatibilité entre des applications compilées à l'aide de compilateurs différents et qui utilisent ce format par défaut. Cependant, il y a toujours un risque que quelqu'un compile le plugin avec un compilateur différent et que l'interface binaire de l'application soit logée ailleurs que dans l'application. Et que se passe-t-il si vous décidez un jour de livrer votre application sur un autre système d'exploitation ? La nouvelle version ne sera pas capable d'utiliser les plugins compilés pour d'autres systèmes. Vous devrez demander aux développeurs de compiler leurs plugins pour la nouvelle plateforme. Cela pourrait être difficile, voire impossible.
III-C. Des plugins véritablement portables▲
La meilleure solution est d'utiliser un des langages interprétés. Pourquoi est-ce la meilleure solution ? Parce que vous pouvez toujours écrire votre propre interpréteur de ce langage et l'attacher à votre logiciel. Vous serez probablement capable d'utiliser un des interpréteurs existants. Comme je l'ai mentionné plus haut, il existe au moins deux bons langages que vous pouvez utiliser pour implémenter l'interface du plugin dans votre logiciel. Je pense que JavaScript est moins bon que Python. Python est plus méthodique et comprend beaucoup de possibilités intégrées que JS ne contient pas.
III-D. Java au lieu de C++ ?▲
Que se passe-t-il si les plugins ne sont pas quelque chose d'exotique dans votre programme, mais sont implémentés comme une part importante de l'application avec tous les droits ? C'est sans doute une bonne raison d'abandonner C++ et d'utiliser un langage qui possède sa propre couche entre le code exécutable et le système d'exploitation. Cette méthode est utilisée par Eclipse. Eclipse est une plateforme écrite en Java. Eclipse tout nu est inutilisable. Ses fonctionnalités principales sont fournies par les plugins. Lorsque vous voulez écrire en C++, vous utilisez Eclipse CDT, en PHP vous utilisez Eclipse avec un jeu différent de plugins. Il y a peu, j'ai vu un environnement de développement intégré Eclipse pour Arduino. Eclipse peut être exécuté sur tous les systèmes qui possèdent une machine virtuelle Java.
À mon avis, le meilleur langage est Python. Il est également disponible sur différentes plateformes, mais il est plus rapide. De plus, vous pouvez compiler son code en code Java exécutable (à l'aide de Jython) qui pourra fonctionner sur des systèmes qui implémentent Java et pas Python (par exemple de vieux appareils mobiles).
III-E. Commencer avec la bibliothèque partagée POCO ?▲
Revenons au C++. Lorsque nous fournissons des plugins, compilés par nous-mêmes, pour des systèmes d'exploitation différents, nous pouvons omettre le problème de différences d'interface binaire de l'application. Nous pouvons maintenant nous occuper de l'interface de programmation. En d'autres termes, nous devons maintenant penser à la programmation des parties de l'application d'une façon portable du point de vue du code. Un code bien écrit peut être compilé sans changements sur tous les systèmes d'exploitation de pointe. Nous pouvons utiliser notre propre bibliothèque ou bien dépendre de bibliothèques externes qui fournissent une interface pour bibliothèques partagées. J'ai testé le composant Poco::SharedLibrary et je pense qu'il est satisfaisant à beaucoup d'égards. Il fournit des méthodes de chargement pour chacune des interfaces de programmation des systèmes d'exploitation les plus populaires.
POCO est un outil très complexe et bien documenté, je ne vais donc pas le décrire dans cet article. Je recommande de lire cette présentation pour obtenir quelques informations sur cette bibliothèque et la documentation officielle pour parfaire vos connaissances.
Dans une future partie de l'article traitant de la programmation modulaire, je vous montrerai comment écrire une application utilisant Boost::Python.
III-F. Remerciements▲
Cet article est une traduction autorisée de l'article paru sur le site de Kacper Kolodziej.
Merci aussi à Claude Leloup pour sa relecture orthographique.