Salome HOME
mergefrom branch BR_V511_PR tag mergeto_trunk_03feb09
[modules/yacs.git] / doc / compInterne.rst
1
2 .. _seccompinterne:
3
4 Mise sous forme d'objet interne
5 ===============================
6
7 .. index:: single: objet interne
8
9 Dans la suite de ce document, on supposera qu'un **objet interne** est un
10 **objet C++ ou python**   qui fournit une première interface au code initial.
11 Suivant la forme du code initial (binaire exécutable, librairie statique  ou
12 dynamique, fichiers sources f77, C, C++ ou python), cet objet aura  différentes
13 formes et la communication objet interne --- code initial  sera différente.
14
15
16 Méthodes et attributs de l'objet
17 --------------------------------
18
19 Dans chaque cas, il faudra définir les services et l'état interne   de l'objet
20 interne. En particulier :
21
22 * choisir les différents services de cet objet
23
24 * pour chaque service, définir les données d'entrée et de sortie
25
26 * pour chaque entrée et chaque sortie, définir le type de la donnée  et
27   éventuellement les pré-conditions et post-conditions associées  (par exemple,
28   donnée d'entrée positive)
29
30 * définir l'état interne de l'objet et éventuellement sa valeur  avant et après
31   l'appel aux différents services
32
33 Les **services** seront implémentés sous forme de **méthodes publiques**  et
34 l'**état interne** sous forme d'**attributs**.    Si le concepteur de l'objet
35 désire permettre à l'utilisateur d'accéder  en lecture/écriture aux attributs,
36 il doit fournir des services accédant  à ces attributs.
37
38
39 Routines fortran77/fonctions C/classes C++
40 ------------------------------------------
41
42
43 Principe
44 ^^^^^^^^
45
46 Dans le cas de routines fortran77, de fonctions C et de classes C++,
47 l'intégrateur ajoutera simplement une enveloppe C++ autour de ces fonctions
48 (voir figure :ref:`Objet interne C++ <figobjetinterne>`), pour obtenir l'objet interne.    Chaque
49 méthode de l'objet
50
51 * extrait, si nécessaire, l'information des paramètres d'entrée,
52
53 * appelle la ou les routines internes concernées,
54
55 * met en forme les résultats de ces routines internes dans  les paramètres de
56   sortie.
57
58 .. _figobjetinterne:
59
60
61 .. image:: images/objintcpp.png
62    :width: 54ex
63    :align: center
64
65 .. centered::
66    Objet interne C++
67
68
69 .. _exemple1:
70
71 Exemple 1
72 ^^^^^^^^^
73
74 Soient les routines fortran f77 suivantes effectuant des calculs d'algèbre
75 linéaire sur des tableaux unidimensionnels de flottants :
76
77
78 ``addvec.f``
79
80 .. include:: ./exemples/exemple1/addvec.f
81    :literal:
82
83
84 ``prdscl.f``
85
86 .. include:: ./exemples/exemple1/prdscl.f
87    :literal:
88
89 ainsi qu'une classe C++ simulant un type vecteur (très) rudimentaire :
90
91 .. _vecteur.hxx:
92
93
94 ``vecteur.hxx (interface C++)``
95
96 .. include:: ./exemples/exemple1/exec2/vecteur.hxx
97    :literal:
98
99
100 ``vecteur.cxx (implémentation C++)``
101
102 .. include:: ./exemples/exemple1/exec2/vecteur.cxx
103    :literal:
104
105 L'objet interne (i.e. la classe C++) dans l'exemple est :
106
107
108 ``alglin.hxx``
109
110 .. include:: ./exemples/exemple1/exec2/alglin.hxx
111    :literal:
112
113
114 ``alglin.cxx``
115
116 .. include:: ./exemples/exemple1/exec2/alglin.cxx
117    :literal:
118
119 **Remarques**
120
121   #. Le choix des méthodes, du passage des paramètres et de leur type, est  laissé
122      libre à l'intégrateur (conformément aux souhaits des utilisateurs  de l'objet).
123      La correspondance entre les paramètres de l'objet interne  et ceux des routines
124      du code initial est réalisée par l'implémentation (fichier  ``alglin.cxx``, ci-
125      avant).
126
127   #. En particulier, si des structures MED [MED]_ sont passées en argument
128      d'entrée,   le fichier d'implémentation C++, sera chargé d'extraire et mettre en
129      forme les informations à passer aux routines de calcul internes  (sous forme de
130      tableaux simples et scalaires pour les routines  fortran internes).    Pour les
131      arguments de sortie au format MED, les résultats des routines  internes seront
132      introduites par l'implémentation dans les objets MED  à retourner.
133
134 Dans l'exemple ci-avant, remarquer :
135
136 * la declaration ``extern "C"`` devant les prototypes en C++   des fonctions
137   fortran,
138
139 * le caractère "underscore" ajouté au nom C++ des fonctions  fortran,
140
141 * le mode de passage des arguments, la règle étant : sauf exceptions  (longueur
142   des chaînes de caractères), on passe des pointeurs. Pour les  arguments
143   scalaires, on passe l'adresse de ces scalaires; pour des  arguments pointeurs
144   (tableaux), on passe les pointeurs tels quels.
145
146 L'objet interne  peut maintenant être utilisé dans un code C++ :
147
148
149 .. include:: ./exemples/exemple1/exec2/main_extraits.cxx
150    :literal:
151
152
153 Références
154 ^^^^^^^^^^
155
156 L'encapsulation C/fortran77 dans un code C++ suit la procédure standard
157 (formats des réels/entiers, nom des routines, passage des arguments).  A ce
158 sujet, on pourra consulter, par exemple,   [ForCpp]_ ou [ForCpp2]_.
159
160
161 Fonctions/Classes Python
162 ------------------------
163
164
165 Principe
166 ^^^^^^^^
167
168 Le principe d'encapsulation de fonctions/classes python dans un   objet interne
169 (python) est le même que dans le cas précédent.
170
171   .. _figobjetinterne2:
172
173
174   .. image:: images/objintpy.png
175      :width: 54ex
176      :align: center
177
178   .. centered::
179      Objet interne python
180
181
182 Exemple 2
183 ^^^^^^^^^
184
185 Un exemple similaire au précédent part de fonctions python à encapsuler :
186
187
188 ``func.py``
189
190 .. include:: ./exemples/exemple2/func.py
191    :literal:
192
193 Il est facile d'intégrer ces fonctions dans une classe python :
194
195
196 ``compo.py``
197
198 .. include:: ./exemples/exemple2/compo.py
199    :literal:
200
201 **Remarque**
202   En fait, il n'est même pas nécessaire d'enrober les fonctions python de
203   ``func.py``, mais c'est plus "propre" (en particulier si  l'objet possède un
204   état interne).    Le script ci-après permet d'utiliser l'objet interne python
205   depuis un interpréteur python :
206
207 .. include:: ./exemples/exemple2/exmpl.py
208    :literal:
209
210
211 Code initial sous forme d'exécutables
212 -------------------------------------
213
214
215 Principe
216 ^^^^^^^^
217
218 Ce cas se rencontre lorsqu'on ne dispose pas des sources du code interne  (ou
219 lorsqu'on ne désire pas intégrer ces sources dans l'architecture  interne).
220 On supposera que le code est sous forme d'un binaire exécutable par  le système
221 d'exploitation.    Les communications avec le code peuvent se faire,
222
223 1. en entrée, soit :
224
225    * par un ou plusieurs fichiers,
226    * par la ligne de commande,
227    * en répondant au clavier à des questions du code
228
229 2. en sortie, soit :
230
231    * par un ou plusieurs fichiers,
232    * à l'affichage écran.
233
234 La communication avec les exécutables se fait à l'aide des commandes
235 (disponibles en C++ et en python) :
236
237 * ``system`` : lancer un exécutable avec lequel on communique en entrée via
238   fichiers ou la ligne de commande, en sortie, via fichiers;
239
240 * ``popen`` : mêmes fonctionnalités que le cas précédent, avec en plus la
241   possibilité de   récupérer la sortie standard (écran) de l'exécutable.
242
243 Les commandes ci-dessus sont rangées par ordre de complexité croissante (on
244 conseille d'utiliser  autant que possible ``system``).
245
246
247 Exemple 3 : Objet interne python, connecté à des exécutables externes.    
248 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
249
250
251 On désire utiliser
252 un objet "Systeme" qui possède 5 services :
253
254 * ``cd``, qui, à partir d'un chemin (chaîne de caractères), positionne  un
255   répertoire courant,
256
257 * ``cp``, qui, à partir de 2 noms de fichiers, copie le premier  fichier sur le
258   second dans le répertoire courant;
259
260 * ``touch``, qui, à partir d'un nom de fichier, met à jour la  date du fichier
261   s'il existe, le crée sinon;
262
263 * ``rm``, qui, à partir d'un nom de fichier, détruit le fichier   dans le
264   répertoire courant;
265
266 * ``dir``, qui liste les fichiers contenus dans le répertoire courant.
267
268 L'état interne de l'objet sera constitué du nom du répertoire courant  dans
269 lequel travailleront les services de l'objet  (qui est positionné  par le
270 service ``cd``).    
271
272 En python, la classe de l'objet pourrait s'écrire :
273
274
275 ``systeme.py``
276
277 .. include:: ./exemples/exemple3/systeme.py
278    :literal:
279
280 et son utilisation depuis l'interpréteur python :
281
282
283 .. include:: ./exemples/exemple3/use.py
284    :literal:
285
286
287 **Remarques**
288
289   #. Ceci est donné à titre d'exemple, python possède en standard  tout ce qu'il
290      faut pour rendre ces services, sans passer par des commandes  systèmes
291      (``system`` et ``popen``).
292
293   #. L'exemple illustre le passage d'arguments d'entrées par la ligne   de
294      commandes (noms passés en argument) et la "capture" des sorties écran  des
295      exécutables extérieurs (``system`` ne permet pas de récupérer simplement  la
296      sortie standard de la commande unix ``ls``, on utilise ``popen`` dans ce cas).
297
298
299 .. _exemple4:
300
301 Exemple 4 : Objet interne connecté à un exécutable externe.    
302 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
303 Cet exemple montre une
304 interface (très) partielle d'un exécutable binaire *FreeFem* [FreeFem]_ sous la
305 forme d'un objet C++. L'interface donne  accès à la définition d'une géométrie
306 2D par sa frontière ainsi que la  résolution approchée d'une équation simple
307 (convection forcée) sur cette géométrie.    Les différentes méthodes de l'objet
308 interne sont :
309
310 * une méthode qui enregistre la géométrie du domaine,
311
312 * une méthode qui enregistre le champs de vitesse convectante,
313
314 * la méthode de calcul qui reçoit la condition initiale (sous   forme analytique
315   --- chaîne de caractères), le pas de temps et le nombre  de pas de temps.
316
317 L'état interne de l'objet est constitué de la géométrie et du champs  de
318 vitesse.    La méthode de calcul crée un fichier à partir de ses paramètres et
319 de  l'état interne, puis lance une boucle de calcul (par un appel système).
320 Les résultats du calcul ne sont pas récupérés par l'objet.
321
322 **Remarques**
323
324   #. Une encapsulation complète de FreeFem demanderait un effort beaucoup  plus
325      important, ceci n'est qu'un exemple.
326
327   #. On ne récupère pas ici de résultat dans l'objet C++ (l'évolution  est
328      seulement visualisée par le moteur graphique interne de FreeFem).  Si on
329      désirait le faire, il faudrait après  l'appel système, relire le fichier produit
330      par le code externe, et  renvoyer les résultats sous forme compréhensible par
331      l'utilisateur  de l'objet interne
332
333 Deux versions (C++ et python) sont listées ci-après.
334
335 .. _freefem.hxx:
336
337
338 ``FreeFem.hxx``
339
340 .. include:: ./exemples/exemple4/FreeFem.hxx
341    :literal:
342
343
344 ``FreeFem.cxx``
345
346 .. include:: ./exemples/exemple4/FreeFem.cxx
347    :literal:
348
349
350 ``FreeFem.py``
351
352 .. include:: ./exemples/exemple4/FreeFem.py
353    :literal:
354
355 L'utilisation depuis un code C++ ou un interpréteur python est similaire  dans
356 les 2 versions :
357
358
359 ``version C++``
360
361 .. include:: ./exemples/exemple4/main.cxx
362    :literal:
363
364
365 ``version python``
366
367 .. include:: ./exemples/exemple4/useFreeFem.py
368    :literal:
369