4 Composant à accès local
5 =======================
11 Comme indiqué au chapitre :ref:`secetapes`,
12 l'objet interne construit au chapitre :ref:`seccompinterne`
13 peut être manipulé depuis un interpréteur python
14 local, suivant le schéma ci-après.
19 .. image:: images/accesLocal.png
23 .. centered:: Accès depuis un interpréteur python local
25 Dans le cas d'un objet interne C++, il faudra écrire une interface python-C++
26 pour obtenir un composant local. L'écriture de cette interface fera l'objet de
27 la section suivante. Dans le cas d'un objet interne python, il n'y a rien à
28 faire : l'objet interne python peut être utilisé tel quel comme composant
32 A partir d'un objet interne python
33 ----------------------------------
35 Si l'objet interne est implémenté comme objet python, il n'est pas nécessaire
36 d'introduire une interface supplémentaire.
39 A partir d'un objet interne C++
40 -------------------------------
42 Pour pouvoir utiliser un objet C++ à partir d'un interpréteur python, il faut
43 passer par une interface python/C++. Cette interface peut être codée par
44 l'intégrateur ou être générée (semi-) automatiquement à l'aide d'outils tels
45 que swig [SWIG]_ ou boost [BOOST]_. On envisagera ici la génération de
46 l'interface à l'aide de swig, à l'aide d'un exemple simple. Pour le traitement
47 de cas particuliers, on renvoit à la documentation de swig, voire à la
48 documentation de python.
51 Fichier d'interface swig
52 ^^^^^^^^^^^^^^^^^^^^^^^^
54 La procédure standard pour utiliser swig est d'écrire un **fichier d'interface**
55 (se terminant par ``.i``). Ce fichier d'interface ressemble fortement à une
56 fichier d'interface C++ (voir par exemple ``vecteur.hxx`` ou
57 ``FreeFem.hxx``). Il contient toutes les déclarations C++
58 (structures, fonctions, classes, constantes, ...) que l'intégrateur veut
59 "exporter" au niveau python. Dans le cas des classes C++, seule la partie
60 publique des classes peut être indiquée dans le fichier d'interface. Des
61 exemples seront donnés plus loin.
64 Processus de génération du code de l'interface C++/python
65 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
68 Les extensions au langage python, écrites en langage C/C++/f77 (langages
69 compilés autres que python), doivent être compilées sous forme de librairies
70 dynamiques (``.so`` sous unix, ``.dll`` sous windows). Depuis l'interpréteur
71 python, on chargera ces extensions au moyen de la commande ``import``.
73 Tous les composants à intégrer seront donc compilés sous forme de librairie
74 dynamique, ce qui impliquera une procédure particulière pour l'utilisation des
75 outils de débogages (voir plus loin). Les différentes opérations à effectuer
76 et les fichiers intervenant dans le processus sont schématisés par la figure
82 .. image:: images/accesLocalCpp.png
86 .. centered:: Interface via swig
89 Exemple 5 (première version)
90 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
92 Si on veut accéder depuis un interpréteur python local à la classe ``alglin``,
93 on écrira un fichier d'interface du type :
100 .. include:: ./exemples/exemple5/v1/alglin.i
103 Les différentes lignes signifient : ::
107 Définit le nom du module python. Pour importer les définitions du composant
108 depuis un interpréteur python, on écrira : ``import AlgLinModule``. ::
111 #include "alglin.hxx"
114 Entre les lignes ``%{`` et ``%}``, on indique les déclarations C++ dont le code
115 de l'interface C++/python aura besoin (sinon le fichier C++ généré par swig ne
116 compilera pas). Typiquement, on inclut ici le fichier d'interface de l'objet
117 interne C++ construit au chapitre précédent. ::
123 void addvec (vecteur *C, vecteur *A, vecteur *B);
124 double prdscl (vecteur *A, vecteur *B);
125 vecteur * create_vector (long n);
126 void destroy_vector (vecteur *V);
130 On indique dans le reste du fichier ``alglin.i``, les classes et définitions
131 que l'on désire exporter vers l'interpréteur python. Exemple d'usage de
132 l'interface générée :
135 .. include:: ./exemples/exemple5/v1/sortie.txt
140 #. Par rapport à la déclaration de la classe C++ (fichier ``alglin.hxx``), on a
141 introduit un constructeur (``alglin()``) et un destructeur (``~alglin()``).
142 Dans la classe C++ de l'objet interne, ces constructeur et destructeur ne sont
143 pas nécessaires (l'objet interne n'a pas besoin d'être initialisé à sa création
144 et ne gère pas de mémoire dynamique C++). Le compilateur fournit un
145 constructeur et un destructeur par défaut dans ce cas. Pour le fichier
146 d'interface swig, par contre, **il faut** déclarer explicitement un
147 constructeur et un destructeur pour que python puisse gérer correctement la
148 mémoire C++ (i.e. quand un objet python est créé/détruit, l'objet C++ interne
149 soit aussi créé/détruit "proprement").
151 #. Remarquer que dans le fichier d'interface ``alglin.i``, on n'explicite pas
152 la définition de la structure/classe ``vecteur``. Les objets de type
153 ``vecteur`` seront vus depuis l'interpréteur python comme des objets "boîte
154 noire" (on connait leur type et leur emplacement mémoire mais pas les
155 méthodes/attributs associés). Si on essaie d'appeler une méthode sur un objet
156 vecteur, on obtient le message d'erreur suivant :
158 .. include:: ./exemples/exemple5/v1/sortie2.txt
164 La deuxième version de cet exemple (ci-après) corrigera ce problème.
169 Exemple 5 (deuxième version)
170 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
172 La première version de l'exemple souffre de deux défauts (parmi d'autres ...),
173 concernant les objets de type vecteur :
175 * on n'a pas accès aux méthodes ni aux attributs d'objets de la classe vecteur
176 (cf. la seconde remarque ci-dessus),
178 * rien n'est prévu pour initialiser/modifier les coefficients contenus dans un
181 swig permet d'enrichir le fichier d'interface ``alglin.i``
182 pour ajouter les fonctionnalités manquantes :
187 ``alglin.i (version 2)``
189 .. include:: ./exemples/exemple5/v2/alglin.i
193 Par rapport à la version précédente, on a la déclaration de
194 la classe vecteur, ce qui donne par exemple accès à la taille des vecteurs et à
195 une "poignée" sur les coefficients (mais pas sur les coefficients
196 individuellement). La troisième version corrigera ce défaut. Un exemple
197 d'utilisation du composant (et de la limitation sur l'accès aux vecteurs) est :
199 .. include:: ./exemples/exemple5/v2/sortie.txt
203 Exemple 5 (troisième version)
204 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
206 La deuxième version de l'exemple permet de "voir" les objets de type vecteur
207 mais seulement en "surface". En particulier, on n'a pas accès aux coefficients
208 individuellement depuis l'interpréteur python. La troisième version, en
209 ajoutant dans l'interface ``alglin.i`` des fonctions utilitaires
210 (``__setitem__`` et ``__getitem__``) permet de simuler (partiellement) depuis
211 la couche python de véritables vecteurs de coefficients.
215 une fonction d'affichage\ ``__str__``, qui permet, quand on exécute ``print
216 v`` depuis l'interpréteur, d'afficher la liste des coefficients de v.
221 ``alglin.i (version 3)``
223 .. include:: ./exemples/exemple5/v3/alglin.i
226 Un exemple d'utilisation du composant (y compris l'accès aux vecteurs) est :
229 .. include:: ./exemples/exemple5/v3/sortie.txt