]> SALOME platform Git repositories - modules/yacs.git/blob - doc/accesLocal.rst
Salome HOME
mergefrom branch BR_V511_PR tag mergeto_trunk_03feb09
[modules/yacs.git] / doc / accesLocal.rst
1
2 .. _secacceslocal:
3
4 Composant à accès local
5 =======================
6
7
8 Principe
9 --------
10
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.
15
16 .. _figacceslocal2:
17
18
19 .. image:: images/accesLocal.png
20    :width: 46ex
21    :align: center
22
23 .. centered::   Accès depuis un interpréteur python local
24
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
29 local.
30
31
32 A partir d'un objet interne python
33 ----------------------------------
34
35 Si l'objet interne est implémenté comme objet python, il n'est pas nécessaire
36 d'introduire une interface supplémentaire.
37
38
39 A partir d'un objet interne C++
40 -------------------------------
41
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.
49
50
51 Fichier d'interface swig
52 ^^^^^^^^^^^^^^^^^^^^^^^^
53
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.
62
63
64 Processus de génération du code de l'interface C++/python
65 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
67 **Règle**
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``.    
72
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
77 suivante.
78
79 .. _processusswig:
80
81
82 .. image:: images/accesLocalCpp.png
83    :width: 45ex
84    :align: center
85
86 .. centered::   Interface via swig
87
88
89 Exemple 5 (première version)
90 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
91
92 Si on veut accéder depuis un interpréteur python local à la classe  ``alglin``,
93 on écrira un fichier d'interface du type :
94
95 .. _alglin.i.v1:
96
97
98 ``alglin.i``
99
100 .. include:: ./exemples/exemple5/v1/alglin.i
101    :literal:
102
103 Les différentes lignes signifient :     ::
104
105    %module AlgLinModule
106
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``.     ::
109
110    %{
111    #include "alglin.hxx"
112    %}
113
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.     ::
118
119    class alglin {
120    public:
121      alglin ();
122      ~alglin ();
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);
127    
128    };
129
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 :
133
134
135 .. include:: ./exemples/exemple5/v1/sortie.txt
136    :literal:
137
138 **Remarques**
139
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").
150
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 :
157   
158 .. include:: ./exemples/exemple5/v1/sortie2.txt
159    :literal:
160
161
162 .. epigraph::
163
164    La deuxième version de cet exemple (ci-après) corrigera ce problème.
165
166    .. % 
167
168
169 Exemple 5 (deuxième version)
170 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
171
172 La première version de l'exemple souffre de deux défauts (parmi d'autres ...),
173 concernant les objets de type vecteur :
174
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),
177
178 * rien n'est prévu pour initialiser/modifier les coefficients  contenus dans un
179   objet vecteur.
180
181 swig permet d'enrichir le fichier d'interface ``alglin.i`` 
182 pour ajouter les fonctionnalités manquantes :
183
184 .. _alglin.i.v2:
185
186
187 ``alglin.i (version 2)``
188
189 .. include:: ./exemples/exemple5/v2/alglin.i
190    :literal:
191
192 **Remarque**
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 :
198
199 .. include:: ./exemples/exemple5/v2/sortie.txt
200    :literal:
201
202
203 Exemple 5 (troisième version)
204 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
205
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.    
212
213 **Remarque**
214   On a aussi ajouté
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.
217
218 .. _alglin.i.v3:
219
220
221 ``alglin.i (version 3)``
222
223 .. include:: ./exemples/exemple5/v3/alglin.i
224    :literal:
225
226 Un exemple d'utilisation du composant (y compris l'accès aux vecteurs) est :
227
228
229 .. include:: ./exemples/exemple5/v3/sortie.txt
230    :literal:
231