Sommaire
Programme C++ embarquant Python
Introduction
Cet exemple permet de créer un executable python sous Visual C++ embarquant du code C++. Ce procédé permet notament de pouvoir tester des classes C++ de manière souple à l'aide de script python.
Prérequis
Il faut installer au préalable :
- - Visual C++ 6
- Python pour windows (http://www.python.org)
- Swig.exe pour windows (http://www.swig.org)
- Classes d'interface C++ des types Python (http://www.mcmillan-inc.com/scxx.html),
les placer dans un répertoire au dessus du projet nommé lib/scxx
Fichiers de la commande Python
Créer les fichiers ExempleHppFichier et exemple.cpp_, ces fichiers contiennent le code des commandes qui vont être ajoutées à Python.
A NOTER: l'inclusion des fichiers scxx/PWO*.h est encadré par #ifndef SWIG ceci afin de ne pas être pris en compte par le générateur d'interface de SWIG.
Fichier d'interface de SWIG
Créer le fichier ScxxIfichier, ce fichier définit le comportement que doit prendre SWIG lorsqu'il rencontre une classe de la librairie scxx
Créer un fichier ExempleIppFichier servant à SWIG. SWIG est un générateur d'interface de module C pour Python. Il simplifie la connexion de module en C avec le langage Python.
A NOTER: l'inclusion des fichiers d'entètes scxx/PWO*.h, ces fichiers contiennent toutes les classes C++ pour accéder aux différents types Python (Tuple, List, Map, etc...). Elle doit être suivi par %include scxx.i.
Fichier du programme principal
Créer le fichier MainCppFichier
REMARQUE: ne pas oublier l'extern "C" qui permet aux fonctions C d'être trouvées par le linker de visual.
REMARQUE: la fonction d'initialisation du module python est composée de 'init' suivi du nom du module défini dans le fichier d'interface ExempleIppFichier suivi de 'c'. Cette dernière lettre est ajouté par SWIG quand l'option de génération shadow est sélectionnée. Cette option génère les classes Python englobant l'accès aux classes C++, ceci dans le but de simplifier l'accès aux classes C++
Creation d'un projet Visual C++
Créer avec Visual C++ un nouveau projet Win32 Console Application le nommer exemple et le placer dans le répertoire exemple_C++
Ajouter les fichiers sources ExempleHppFichier, exemple.cpp_ et MainCppFichier
Créer un nouveau dossier dans le projet (touche droite souris et sélectionner New Folder)
- Nom : Swig interface
- Extension : *.i
Ajouter le fichier ExempleIppFichier au projet visual
Ajouter au projet Visual tous les fichiers sources du répertoires lib\\scxx
Configuration du générateur SWIG
Sélectionner dans le menu Projects le sous menu Settings...
Cliquer sur le fichier ExempleIppFichier de la boite de dialogue Project Settings
Cliquer sur l'onglet Custom Build
Ajouter dans le champ de saisie Commands la ligne suivante :
set SWIGPATH=C:\SWIG %SWIGPATH%\swig.exe -python -shadow -I..\lib\scxx -I%SWIGPATH%\lib\python -I%SWIGPATH%\lib -c++ -o $(ProjDir)\$(InputName)_win32.cpp $(InputPath)
Ajouter dans le champ de saisie Outputs la ligne:
$(ProjDir)\$(InputName)_win32.cpp
Le set SWIGPATH=C:\SWIG doit contenir le chemin de SWIG. Cette variable d'environnement peut être ajoutée directement dans le fichier AUTOEXEC.BAT (penser à rebooter dans ce cas)
Cliquer sur le bouton Dependencies
Ajouter les fichiers ExempleHppFichier et ExempleIppFichier, ils conditionnent la recompilation par SWIG du fichier d'interface ExempleIppFichier
A NOTER : l'appel au générateur SWIG diffère de la version C, l'option -shadow a été ajoutée, cette option permet de générer une classe d'interface en Python sur la classe à tester, l'option -c++ a été ajoutée, cette option permet de créer une interface pour les classes C++.
REMARQUE : la génération par SWIG avec l'option -shadow, créé un module exemple.py, ce module contient une classe Python nommée Classe, ses méthodes sont identiques à celles de la classe C++.
Paramètrage du projet
Sélectionner dans le menu Projects le sous menu Settings...
Cliquer sur la racine du projet et cliquer le l'onglet C/C++
Sélectionner dans Category le choix Code generation
Sélectionner dans Use run-time library le choix Multithreaded DLL
Sélectionner dans Category le choix Preprocessor
Supprimer _DEBUG dans le champ de saisie Preprocessor definitions. La suppression de cette définition permet de pouvoir se linker sans problème avec la librairie Python livrée en standard. Si l'on possède la librairie Python de debug, on peut laisser cette définition.
Ajouter ..\\lib dans Additional include directories pour la librairie scxx.
Paramètrage de Visual C++
Sélectionner le sous menu Options du menu Tools
Sélectionner l'onglet Directories dans la boite de dialogue Options
Sélectionner dans Show directories for: l'option Include files
Ajouter le répertoire contenant le fichier python.h
Sélectionner dans Show directories for: l'option Library files
Ajouter le répertoire contenant le fichier pythonXX.lib, XX correspond à la version de la librairie
REMARQUE: Ce paramêtrage a l'avantage d'être effectué une bonne fois pour toute et n'est valable que sur la machine courante. L'avantage, si l'on change de machine est que si Python n'est pas installé dans le même répertoire, il suffit de positionner ces paramêtres et tous les projets Visual se recompileront et se linkeront sans aucun problème.
Compilation du projet
La première compilation doit générer automatiquement un fichier exemple_win32.cpp, il faut ajouter ce fichier dans le projet pour pouvoir bénéficier des nouvelles commandes contenues dans le fichier exemple.cpp_
Execution du programme
Pour executer le programme, ouvrir une une fenêtre MS/DOS, se placer sur le répertoire racine du projet et taper :
C:\exempleSwig\exemple_C++>Debug\exemple.exe
Les lignes suivantes apparaissent :
Python 2.1.1 (#20, Jul 20 2001, 01:19:29) [MSC 32 bit (Intel)] on win32 Type "copyright", "credits" or "license" for more information. >>>
Une nouvelle classe Python se dénomant Classe est intégrée à ce programme.
Pour pouvoir utiliser cette classe il faut impérativement importer ce module :
>>> import exemple >>>
Ensuite il suffit d'exécuter les commandes suivantes :
>>> obj = exemple.Classe() New Classe >>> obj.setValue ("titi") SetValue Classe : titi >>> print obj.getValue () GetValue Classe : titi titi >>> del (obj) Delete Classe >>>