Sam & Max » compiler http://sametmax.com Du code, du cul Sat, 07 Nov 2015 10:56:13 +0000 en-US hourly 1 http://wordpress.org/?v=4.1 Embeder Python dans du C ou C++ 6 http://sametmax.com/embeder-python-dans-du-c-ou-c/ http://sametmax.com/embeder-python-dans-du-c-ou-c/#comments Wed, 14 Jan 2015 03:21:25 +0000 http://sametmax.com/?p=15727 documentée. Il est donc possible de créer des objets Python, charger un module Python ou exécuter une fonction Python depuis un code C et compiler tout ça.]]> L’implémentation de référence de Python est écrite en C, et son API est exposée et bien documentée. Il est donc possible de créer des objets Python, charger un module Python ou exécuter une fonction Python depuis un code C/C++ et compiler tout ça.

Mettons que j’ai dans un fichier biblio.py :

def yolo(arg):
    return arg.upper() + ' !!'

Je peux écrire un fichier prog.c qui l’utilise :

#include <Python.h>
 
int main () {
    // PyObject est un wrapper Python autour des objets qu'on
    // va échanger enter le C et Python.
    PyObject *retour, *module, *fonction, *arguments;
    char *resultat;
 
    // Initialisation de l'interpréteur. A cause du GIL, on ne peut
    // avoir qu'une instance de celui-ci à la fois.
    Py_Initialize();   
 
    // Import du script. 
    PySys_SetPath("."); // Le dossier en cours n'est pas dans le PYTHON PATH
    module = PyImport_ImportModule("biblio");
 
    // Récupération de la fonction
    fonction = PyObject_GetAttrString(module, "yolo");
 
    // Création d'un PyObject de type string. Py_BuildValue peut créer
    // tous les types de base Python. Voir :
    // https://docs.python.org/2/c-api/arg.html#c.Py_BuildValue
    arguments = Py_BuildValue("(s)", "Leroy Jenkins"); 
 
    // Appel de la fonction.
    retour = PyEval_CallObject(fonction, arguments);
 
    // Conversion du PyObject obtenu en string C
    PyArg_Parse(retour, "s", &resultat);
 
    printf("Resultat: %s\n", resultat);
 
    // On ferme cet interpréteur.
    Py_Finalize(); 
    return 0;
}

Là je mets du C, mais la seule vraie différence avec du C++, c’est qu’on aurait cout au lieu de printf.

Pour compiler tout ça, il faut les headers Python et un compilateur. Sous Ubuntu, c’est un simple :

sudo apt-get install python-dev gcc

Et on a tout nos .h dans /usr/include/python2.7. On gccise :

gcc -I/usr/include/python2.7 prog.c -lpython2.7 -o prog -Wall  && ./prog

Même pas un warning, c’est beau.

./prog
Resultat: LEROY JENKINS !!

C’est un exemple simple, mais comme vous le savez je suis une grosse burne en C, donc je ne pourrai pas porter l’expérience plus loin.

Je ne le recommande pas pour rendre votre programme scriptable en Python. Il vaut mieux permettre à Python d’appeler votre code C dans ce cas. Des outils comme cffi rendent cela beaucoup plus facile et rentable que tout faire tout le taff à la main. D’ailleurs si quelqu’un est chaud pour faire un tuto sur cffi…

Non, c’est plus dans le cas où vous avez un programme C, un programme Python, et votre programme C veut utiliser le programme Python sans avoir à tout réécrire. Ou pour le cas où vous avez décidé d’écrire une grosse partie de votre programme en Python pour profiter de sa productivité, mais que vous ne pouvez pas installer Python sur la machine sur laquelle vous aller installer le programme. Bon, y a PyInstaller et Nuitka pour ça également hein, donc tentez avant de tout embeder comme un bourrin.

Ça reste intéressant de voir les entrailles de CPython et à quel point il joue bien avec les langages bas niveaux.

]]>
http://sametmax.com/embeder-python-dans-du-c-ou-c/feed/ 6