Créer des extensions Python à mon programme C++

l'interface C++/Python à l'envers

a marqué ce sujet comme résolu.

Salut.

Je me renouvelle un peu dans l’art de la prog et j’essaie de faire un petit logiciel que je voudrais rendre extensible. Maintenant, j’ai envie de m’embêter un peu et de permettre l’écriture de ces plugins en Python ; en sachant qu’il est largement possible d’interpréter des classes C++ en Python, serait-il possible de faire l’inverse dans mon cas ?

Par exemple, pourrais-je par un quelconque moyen créer et intégrer un plugin écrit en Python pour mon programme C++ ? Si oui, comment à peu près ?

Merci d’avance.

+0 -0

Salut,

Si j’ai bien compris, tu cherches à faire de l'embedding: embarquer le runtime python dans ton programme C++.

Tu trouveras ce qu’il te faut pour commencer sur ce sujet dans la documentation: https://docs.python.org/3/extending/index.html la deuxième partie de la page, embedding CPython.

Je l’ai déjà fait pour une de mes applications (aujourd’hui abandonnée).

Si tu n’as jamais embarqué de langage de script dans un programme C++ avant, ce n’est pas évident. Je te conseille de commencer par embarquer un langage plus facile. Lua est celui qui est de loin le plus simple.

Si tu as déjà testé lua et qu’il ne te plais pas et/ou que tu as rencontré ses limites, tu peux essayer d’embarquer Python. Mais c’est clairement plus difficile

Python a en outre un gros problème de sécurité dans ce contexte. Si tu prévois de distribuer ton logiciel C++ et laisser les utilisateurs écrire des plugins python, sache qu’il est pratiquement impossible de blinder le runtime pour éviter que des utilisateurs mal intentionnés distribuent des scripts dangereux. Cela, entres autres, parce que la fonction open est trop bien implantée au coeur de python, et qu’il y a toujours moyen de la récupérer par des moyens détournés même si on a bloqué les imports les plus évidents.

de ce côté-là, les langages de script plus modestes comme lua sont beaucoup mieux armés, car on peut facilement bloquer les fonctions dont on ne veut pas que les utilisateurs finaux se servent sans filtre.

Pense à ça au cas Oû, car même si ton succès est très relatif avec seulement quelques dizaines d’utilisateurs, c’est ta propre crédibilité qui est en jeu. par expérience il y a toujours des power users qui cherchent la petite bête, et qui finissent toujours par la trouver.

+2 -0

Merci pour ta réponse QuentinC.

Je retiens ce que tu me dis pour le coup, même si je pense que tu ne m’as pas entièrement compris. Le concept d’embedding m’intéresse, mais si j’ai correctement saisi ce que tu me dis, tu penses que je voudrais lancer un programme Python dans la source du code C++.

Je voudrais par exemple pouvoir rajouter (par exemple avec PyQt) des commandes à une toolbar à mon programme Qt natif en C++, pour pouvoir étendre les capacités de mon programme écrit en C++ mais avec des plugins écrits plus simplement en Python.

Ex. : modifier certaines instances déjà initialisées dans le programme, comme la barre des tâches, ajouter de nouvelles fonctionnalités, etc.

Un peu le rôle d’un DLL en quelque sorte, mais qui serait écrite en Python pour rendre l’implémentation beaucoup plus simple.

+0 -0

Oui, c’est donc bien de l’embedding que tu cherches à faire. Très grossièrement, ça se résume en trois points:

  1. Instancier un runtime python dans ton programme C++, ou autrement dit démarrer une VM
  2. Enregistrer les classes, objets, méthodes et fonctions spécifiques à ton programme C++ que l’utilisateur pourra utiliser dans ses scripts python. Ca c’est ce qu’on appelle le binding.
  3. Et enfin lancer les scripts python demandés / configurés par l’utilisateur

C’est ni plus ni moins ce que j’ai fait pour un petit éditeur de texte, à cela près que c’est du win32 au lieu de QT.

Un peu plus tard, je me suis finalement dit que je n’avais pas besoin de C++, et j’ai recommencé le projet pour le refaire entièrement en python; j’en ai profité pour passer à wxPython, et c’est bien mieux ainsi. Peut-être que tu devrais aussi te poser la question est-ce que tu as vraiment besoin de C++, vu que pyQT existe.

Bien sûr, le faire en pur python ne règle pas le problème de sécurité que j’évoquais au post précédent, mais vu que mon projet est un éditeur de texte à destination des développeurs, je suis parti du principe qu’ils sont suffisament éclairés sur le sujet pour vérifier la provenance avant d’exécuter des plugins.

Par contre, à un moment, j’ai envisagé d’embarquer python pour un jeu en C++. Là par contre on a intérêt à blinder son truc, car la plupart des joueurs n’ont pas la conscience informatique de base pour vérifier ce qu’ils téléchargent, et il faut quelque chose qui soit simple pour l’utilisateur lambda. Après moultes péripécies qui ont duré plusieurs années, j’en suis arrivé aujourd’hui à créer mon propre langage de programmation plutôt que développer mon jeu…


Mintenant vu que tu parles de PyQT, tu dois aussi faire gaffe à ce que les objets QT puissent être manipulés indifféremment dans les deux langages, peu importe où ils sont créés et détruits. Ca c’est pas sûr, il faut que tu regardes la doc de QT. De plus, si ton programme C++, la DLL de python, et la DLL de PyQT n’ont pas été compilés exactement avec le même compilateur et les mêmes options, tu as de gros risques que ça explose aléatoirement.

J’aurais eu ce problème si j’avais utilisé wxWidgets pour mon éditeur de texte C++, car mon compilateur est MinGW, et la DLL de python 3.4 et wxPython ont probablement été compilés avec Visual Studio. J’avais pas envie de passer mon temps à chercher comment compiler python à la main; installer et configurer des build tools à n’en plus finir est un truc qui me fait ch####, et ça n’apporte absolument rien à mon plaisir personnel. J’ai eu un conflit de version de MSVCRT, ça m’a amplement suffi.

Ca marche avec python 3.4 seul car toute l’interface du runtime python est en C, et les ABI C sont compatibles entre les deux compilateurs, ce n’est pas le cas du C++.

+0 -0

J’aimerais enfoncer le clou sur un point : CPython est génial quand il s’agit de donner accès à des bibliothèques natives écrites en C ou C++ dans un projet en Python. Mais l’inverse… même si c’est techniquement possible, c’est chercher les problèmes. CPython est lourd, et si tu as le malheur d’avoir une application multithread, tu multiplies cette lourdeur par le nombre de threads.

Pour étendre un programme C ou C++ (ou Rust ou Go) avec un langage de script, j’aurais plutôt tendance à te conseiller d’utiliser une techno qui a été créé spécifiquement dans ce but, comme lua, qui est beaucoup plus léger, utilisé pour scripter des jeux comme World Of Warcraft, et aussi beaucoup moins complexe : il est facile de comprendre le fonctionnement du runtime Lua en une après-midi. On ne peut pas en dire autant de Python. :)

+0 -0

J’aimerais enfoncer le clou sur un point : CPython est génial quand il s’agit de donner accès à des bibliothèques natives écrites en C ou C++ dans un projet en Python. Mais l’inverse… même si c’est techniquement possible, c’est chercher les problèmes. CPython est lourd, et si tu as le malheur d’avoir une application multithread, tu multiplies cette lourdeur par le nombre de threads.

Pour étendre un programme C ou C++ (ou Rust ou Go) avec un langage de script, j’aurais plutôt tendance à te conseiller d’utiliser une techno qui a été créé spécifiquement dans ce but, comme lua, qui est beaucoup plus léger, utilisé pour scripter des jeux comme World Of Warcraft, et aussi beaucoup moins complexe : il est facile de comprendre le fonctionnement du runtime Lua en une après-midi. On ne peut pas en dire autant de Python. :)

nohar

C’est vrai que je peux remettre en question cette idée ; il faut que je regarde les bases de Lua pour voir si ça vaut vraiment le coup. Mais disons que le programme de test que j’essaie de coder est supposé à la fois proposer une gestion de fichiers Python destinés à être exécutés (comme le RGSS avec RPG Maker) et permettre sa propre extension avec des plugins. Je veux le rendre le plus modulable possible.

Donc proposer les plugins en Lua et les fichiers moteur en Python, d’accord, mais ce ne serait pas un peu complexe à la fin, de devoir apprendre deux langages pour un seul et même logiciel ?

Enfin je dois me compliquer la vie, merci à vous deux pour votre aide !

+0 -0

Donc proposer les plugins en Lua et les fichiers moteur en Python, d’accord, mais ce ne serait pas un peu complexe à la fin, de devoir apprendre deux langages pour un seul et même logiciel ?

Qu’est-ce qui t’empêche de faire des plugins pour le moteur aussi en lua ?

Si tu as peur des performances, détrompes-toi, lua est beaucoup plus proche de la vitesse du C++ que ne l’est CPython. ET c’est encore plus rapide si tu optes pour luajit, ce que tu as tout intérêt à faire vu que tu peux passer de l’un à l’autre en changeant à peu près rien à ton code. Après il faudrait comparer avec pypy pour être complet…

Personnellement, ce qui m’avait fait détourner de lua, c’est surtout:

  • Le besoin d’un système orienté objet plus classique par classe (le système par prototype c’est cool, mais c’est inutilement compliqué je trouve)
  • Une gestion des encodages, car lua est complètement agnostique et ça commence à devenir malpratique quand tu fais du multilingue et jongles avec UTF-8, UTF_16, etc.
  • Les tableaux qui commencent à 1, parce que ça n’a absolument aucun intérêt et parce que ça t’induis en erreur tout le temps
  • La syntaxe … ça c’est personnel, mais je suis tellement habitué aux langages à accolades que j’ai du mal avec les languages begin/end.

Mais mis à part ça, pour des petits scripts c’est suffisant; et bien plus facile à mettre en place que le runtime python. ON apprend assez vite à gérer la pile, et pour la partie binding, une fois qu’on a compris comment faire, il existe des aides pour éviter de tout se farcir les wrappers à la main. Cela dit il existe aussi des aides pour le binding en python, voir par exemple boost::python.

Mais comme l’a très bien dit Nohar, python est quand même beaucoup plus conçu pour fonctionner dans le sens inverse: on crée un programme en python qui utilise des modules en C/C++, plutôt que créer un programme en C++ qui utilise des modules en python.

+0 -0

Donc proposer les plugins en Lua et les fichiers moteur en Python, d’accord, mais ce ne serait pas un peu complexe à la fin, de devoir apprendre deux langages pour un seul et même logiciel ?

Qu’est-ce qui t’empêche de faire des plugins pour le moteur aussi en lua ?

Si tu as peur des performances, détrompes-toi, lua est beaucoup plus proche de la vitesse du C++ que ne l’est CPython. ET c’est encore plus rapide si tu optes pour luajit, ce que tu as tout intérêt à faire vu que tu peux passer de l’un à l’autre en changeant à peu près rien à ton code. Après il faudrait comparer avec pypy pour être complet…

Personnellement, ce qui m’avait fait détourner de lua, c’est surtout:

  • Le besoin d’un système orienté objet plus classique par classe (le système par prototype c’est cool, mais c’est inutilement compliqué je trouve)
  • Une gestion des encodages, car lua est complètement agnostique et ça commence à devenir malpratique quand tu fais du multilingue et jongles avec UTF-8, UTF_16, etc.
  • Les tableaux qui commencent à 1, parce que ça n’a absolument aucun intérêt et parce que ça t’induis en erreur tout le temps
  • La syntaxe … ça c’est personnel, mais je suis tellement habitué aux langages à accolades que j’ai du mal avec les languages begin/end.

Mais mis à part ça, pour des petits scripts c’est suffisant; et bien plus facile à mettre en place que le runtime python. ON apprend assez vite à gérer la pile, et pour la partie binding, une fois qu’on a compris comment faire, il existe des aides pour éviter de tout se farcir les wrappers à la main. Cela dit il existe aussi des aides pour le binding en python, voir par exemple boost::python.

Mais comme l’a très bien dit Nohar, python est quand même beaucoup plus conçu pour fonctionner dans le sens inverse: on crée un programme en python qui utilise des modules en C/C++, plutôt que créer un programme en C++ qui utilise des modules en python.

QuentinC

J’essaie (comme dit plus haut) de créer un programme similaire à RPG Maker, donc je fais mine d’adopter toute une pensée derrière ce simple projet de test ; Lua est assez peu connu du grand public et Python est enseigné aujourd’hui en cours d’informatique (le temps nous dira si c’est vraiment utile..). De plus, les défauts que tu me cites me suffisent largement pour préférer garder Lua à la simple création de plugins : Python me semble plus efficace pour la conception du moteur, qui sera de toute façon lui-même basé sur des bibliothèques en C/C++ pour garder l’avantage de la vitesse.

+0 -0

les défauts que tu me cites me suffisent largement pour préférer garder Lua à la simple création de plugins : Python me semble plus efficace pour la conception du moteur, qui sera de toute façon lui-même basé sur des bibliothèques en C/C++ pour garder l’avantage de la vitesse.

Soit tu fais la base avec le moteur en C++, et tu utilises lua comme langage de script unique.

Soit tu fais ton moteur en python, mais alors tu vas te compliquer inutilement la vie à embarquer du lua, et surtout à exposer des objets python en lua. Lua n’est vraiment intéressant que si la base est en C/C++. Si tu pars sur python, dans ce cas, utilise python lui-même comme langage de script. Ce n’est pas interdit d’importer des modules python externes à partir d’un programme compilé avec Py2Exe, cxFreeze & Co. C’est ce que je fais dans la nouvelle version de mon éditeur de texte écrit totalement en python.

Tu auras juste le problème de sécurité que je t’ai mentionné en premier message, mais vu que tu t’adresses à des développeurs de jeux, tu pourras comme moi partir du principe qu’ils sont assez renseignés pour ne pas exécuter aveuglement du code téléchargé.

Ce qui est certain, c’est que de faire un truc avec à la fois python et lua est une très mauvaise idée. LE fait est que, fondamentalement, python est un langage de script; et on ne jongle pas facilement entre deux langages de script.

Je ne conais pas bien RPGMaker, mais si tu regardes bien, ils ont choisi l’approche n°1, je me trompe ? La base avec le moteur est en C/C++ et il y a un langage de script unique à disposition des utilisateurs. Simplement, lua n’existait pas à l’époque où ils l’ont créé, donc ils ont dû inventer leur langage à eux.

Lua est assez peu connu du grand public et Python est enseigné aujourd’hui en cours d’informatique (le temps nous dira si c’est vraiment utile..)

Ca, ça se tient probablement entres autres aux faits que

1 - Python a une orientation objet basée sur les classes, très répandue, alors que lua a une oreintation objet basée sur des prototypes, moins courante et plus compliquée à appréhender

2 - Une des grandes forces de python est de fournir d’office une bibliothèque de modules conséquente permettant de faire déjà plein de choses diversifiées sans rien installer; lua, seul, sans bibliothèque externe et hors d’un programme hôte, ne permet pas de faire grand chose. Sa petitess en fait une force quand il s’agit de l’embarquer dans quelque chose d’autre, mais pour apprendre la programmation en général, ce n’est pas un argument très intéressant.

3 - Les tableaux qui commencent à 1 (oui encore eux). C’était initialement présenté comme un argument de simplicité pour le profane… sauf que ça n’a pas pris, et maintenant c’est une particularité plus gênante qu’autre chose, car aucun autre langage n’a repris cette idée.

Si tu es courageux, tu peux toujours tenter d’embarquer V8. La popularité de JavaScript n’est plus à faire. J’ai aussi voulu essayer, mais la somme de bordel à mettre en place pour compiler le bouzin m’a vite découragé. Si tu réussis ça m’intéresse.

+0 -0

Soit tu fais la base avec le moteur en C++, et tu utilises lua comme langage de script unique.

Soit tu fais ton moteur en python, mais alors tu vas te compliquer inutilement la vie à embarquer du lua, et surtout à exposer des objets python en lua. Lua n’est vraiment intéressant que si la base est en C/C++. Si tu pars sur python, dans ce cas, utilise python lui-même comme langage de script. Ce n’est pas interdit d’importer des modules python externes à partir d’un programme compilé avec Py2Exe, cxFreeze & Co. C’est ce que je fais dans la nouvelle version de mon éditeur de texte écrit totalement en python.

Justement, tu m’as probablement mal compris. Je veux faire la base du moteur en C++ et utiliser Python en langage de script. Quand je parlais de "plugin", je parlais d’extension propre à l’éditeur comme sur Unity par exemple. Je verrais finalement plus tard pour ceux-ci ; l’important est de faire le moteur.

Tu auras juste le problème de sécurité que je t’ai mentionné en premier message, mais vu que tu t’adresses à des développeurs de jeux, tu pourras comme moi partir du principe qu’ils sont assez renseignés pour ne pas exécuter aveuglement du code téléchargé.

Oui, enfin des débutants pourraient y toucher aussi, on ne sait jamais vraiment qui utilise notre logiciel. Après, je veillerais à créer une sorte de sécurité, dans ou en-dehors du logiciel, pour empêcher ce genre de problème.

Après, dans mon cas, c’est à l’utilisateur de prendre soin de son logiciel, sinon il n’a qu’à le réinstaller :)

Ce qui est certain, c’est que de faire un truc avec à la fois python et lua est une très mauvaise idée. LE fait est que, fondamentalement, python est un langage de script; et on ne jongle pas facilement entre deux langages de script.

Je retiens ça, d’ailleurs ça me semble logique. Malgré leurs différences, ils sont assez loin du format syntaxique des langages de bas niveau comme C et C++.

Je ne conais pas bien RPGMaker, mais si tu regardes bien, ils ont choisi l’approche n°1, je me trompe ? La base avec le moteur est en C/C++ et il y a un langage de script unique à disposition des utilisateurs. Simplement, lua n’existait pas à l’époque où ils l’ont créé, donc ils ont dû inventer leur langage à eux.

Ils ont en effet choisi l’approche n°1 (qui est la plus ludique d’ailleurs) mais n’ont pas vraiment crée leur propre langage : RGSS est une version dérivée du langage Ruby. Ça semble un petit peu vieux en effet, mais à l’époque Python ne devait pas être aussi reconnu, je pense, et ne servait que pour les petits projets. Tu expliques bien le reste.

Lua est assez peu connu du grand public et Python est enseigné aujourd’hui en cours d’informatique (le temps nous dira si c’est vraiment utile..)

Ca, ça se tient probablement entres autres aux faits que

1 - Python a une orientation objet basée sur les classes, très répandue, alors que lua a une oreintation objet basée sur des prototypes, moins courante et plus compliquée à appréhender

2 - Une des grandes forces de python est de fournir d’office une bibliothèque de modules conséquente permettant de faire déjà plein de choses diversifiées sans rien installer; lua, seul, sans bibliothèque externe et hors d’un programme hôte, ne permet pas de faire grand chose. Sa petitess en fait une force quand il s’agit de l’embarquer dans quelque chose d’autre, mais pour apprendre la programmation en général, ce n’est pas un argument très intéressant.

3 - Les tableaux qui commencent à 1 (oui encore eux). C’était initialement présenté comme un argument de simplicité pour le profane… sauf que ça n’a pas pris, et maintenant c’est une particularité plus gênante qu’autre chose, car aucun autre langage n’a repris cette idée.

Je n’aurais pas mieux dit.

Si tu es courageux, tu peux toujours tenter d’embarquer V8. La popularité de JavaScript n’est plus à faire. J’ai aussi voulu essayer, mais la somme de bordel à mettre en place pour compiler le bouzin m’a vite découragé. Si tu réussis ça m’intéresse.

QuentinC

Je vais plutôt rester sur le moteur C++ interfacé en Python, mais je chercherai un peu à me renseigner sur le Lua. Concernant V8, je préfère éviter les technologies Javascript en général, j’ai déjà une syncope en entendant le nom du logiciel alors je te raconte même pas ce que représente sa pratique pour moi :D

+0 -0

Justement, tu m’as probablement mal compris. Je veux faire la base du moteur en C++ et utiliser Python en langage de script. Quand je parlais de "plugin", je parlais d’extension propre à l’éditeur comme sur Unity par exemple. Je verrais finalement plus tard pour ceux-ci ; l’important est de faire le moteur.

Alors réfléchis bien à ce qu’on a déjà dit:

  • Embarquer un runtime python dans un programme C++, c’est relativement compliqué et que moyennement prévu pour
  • Créer un module python développé en C++, ça se fait très bien

Dès lors, je me répète, mais faire la base en C++ et utiliser python comme langage de script n’est pas la meilleure des idées.

Pour mon projet d’éditeur de texte, c’est ce que j’avais fait initialement, intégrer le runtime python en C++; avant de réaliser un certain nombre de mois plus tard qu’en fait c’était inutilement compliqué et qu’après tout, je n’avais pas besoin de m’encombrer du C++. J’ai recommencé pour le refaire entièrement en python et c’est beaucoup plus simple.

Ne fait pas la même erreur que moi, je te dis que ça a été une expérience ratée; pédagogiquement intéressante parce que j’ai appris des choses sur le fonctionnement interne de python et de CPython, mais ratée. Donc, à moins que le fonctionnement interne de CPython t’intéresse, pars sur du full python, ou alors sur le combo C++ et lua.

Si c’est lua qui de chagrine, il existe plein d’autres langages de script. Petite liste ici.

Parmi toute cette liste, outre lua, luajit et CPython, personnellement j’ai essayé AngelScript et Wren. Deux autres expériences intéressantes mais qui ne m’ont finalement pas convaincues, chacune pour leurs raisons: AngelScript parce que certaines choses qui me paraissent essentielles sont à faire soi-même, et Wren parce qu’il n’est pas réentrant (on peut pas imbriquer les appels C++>Wren>C++>Wren). C’est Wren qui m’a inspiré pour partir sur un projet de langage perso, parce que le créateur de Wren a aussi écrit un super bouquin sur le sujet.

Si tu tiens à python, tu remarqueras qu’il existe une version pour le monde de l’embarqué, micropython. Ca peut peut-être t’intéresser.

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte