9 Un composant Salomé est un composant CORBA tel que décrit au chapitre
10 précédent, utilisant des services du noyau Salomé. Il faut également "déclarer"
11 ce composant auprès de Salomé (i.e. fournir ou compléter des fichiers de
12 ressources Salomé avec des informations relatives à ce composant). Les
13 différentes opérations à effectuer sont :
15 1. adapter le fichier IDL,
17 2. déclarer le composant auprès du catalogue de modules de Salomé,
19 3. modifier la classe d'implémentation (C++ ou python) pour
21 - suivre l'adaptation du fichier IDL (point 1),
22 - permettre la supervision du composant par Salomé, dans les différents services du composant.
23 - préparer l'utilisation du service de notification (envoi de messages pour suivre
24 le déroulement des calculs dans le composant) - optionel (mais utile),
26 4. déclarer les éventuelles ressources graphiques.
36 La description IDL est semblable à celle d'un composant CORBA standard avec les
39 * le composant doit faire partie du module (CORBA) de base ``Engines``,
41 * le composant doit hériter du composant de base de Salomé :
42 ``Engines::Component`` (défini dans le fichier IDL ``"SALOME_Component.idl"``),
44 * les services du composant peuvent avoir des paramètres ``in``, ``out``
45 et/ou une valeur de retour, mais pas de paramètres ``inout``.
50 #. Le module ``Engines`` regroupe tous les composants de Salomé, autres que les
51 composants centraux de Salomé.
53 #. Le composant de base ``Engines::Component`` permet de ne pas devoir
54 redéfinir pour chaque composant ajouté au système, les services communs (arrêt,
57 #. Ceci n'est pas une limitation, un paramètre ``inout`` peut se découpler en
58 un paramètre ``in`` et un paramètre ``out`` (de toute façon, c'est sous cette
59 forme que le verront les clients python).
65 Reprenons le fichier IDL ``alglin.idl`` et adaptons-le :
70 .. include:: ./exemples/exemple9/alglin.idl
74 Il faut faire attention quand on définit des structures dans l'IDL (comme la
75 structure ``vecteur`` dans ``alglin.idl``). Le nom choisi ``vecteur`` risque
76 d'être déjà "réservé" par un autre composant Salomé.
82 Des modifications analogues sont effectuées sur le fichier IDL ``FreeFem.idl`` :
87 .. include:: ./exemples/exemple10/FreeFemComponent.idl
91 Inscription au catalogue de modules
92 -----------------------------------
94 Pour être utilisables dans Salomé, les composants doivent s'inscrire auprès de
95 l'un des catalogues de modules de Salomé. Ce catalogue est réparti entre
96 plusieurs fichiers (catalogue général, catalogue utilisateur). On supposera
97 que le composant sera déclaré dans le catalogue personnel d'un utilisateur.
98 Le fichier de catalogue de composants est un fichier XML qui contient
100 #. la liste des services du composant et leurs paramètres,
102 #. la (les) machine(s) où le composant peut être chargé en mémoire, le nom du
103 fichier contenant l'icone du composant, des informations de version,
104 commentaires, service par défaut, etc (ces informations sont optionelles).
106 On peut compléter à la main ce catalogue ou utiliser un utilitaire fourni par
107 Salomé qui génère les informations du point 1 ci-dessus (il faudra malgré tout
108 éditer le fichier pour entrer les informations du point 2). Cet outil est
109 disponible dans l'interface graphique Salomé (menu ``Tools->Catalog Generator``)
110 en indiquant le nom du catalogue (fichier XML) et le nom du fichier IDL du
114 Classe d'implémentation C++
115 ---------------------------
117 **On supposera dans ce paragraphe, que le fichier IDL définit une classe CORBA :
118 A et qu'on utilisera la classe d'implémentation C++ : A_impl.**
121 Mise en conformité avec l'IDL du composant
122 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
124 Pour adapter les classes d'implémentation CORBA/C++ standards (telles que vues
125 au chapitre précédent), il faut :
127 #. insérer le fichier ``SALOMEconfig.h`` : ::
129 #include <SALOMEconfig.h>
131 Le fichier ``SALOMEconfig.h`` contient un certain nombre de définitions utiles
132 pour assurer l'indépendance du code de la classe d'implémentation par rapport à
133 la version de CORBA utilisée.
135 #. insérer ensuite le fichier ``SALOME_Component_i.hxx`` ::
137 #include "SALOME_Component_i.hxx"
139 qui contient l'interface de la classe d'implémentation C++ du composant de base
142 #. pour la classe CORBA qui est implémentée, ajouter la ligne : ::
144 #include CORBA_SERVER_HEADER(A)
146 ``CORBA_SERVER_HEADER`` est une macro définie dans ``SALOMEconfig.h`` et qui
147 assure l'indépendance des noms de fichiers d'inclusion CORBA par rapport à
148 l'implémentation de CORBA utilisée.
150 #. pour chaque classe CORBA qui est utilisée dans la classe d'implémentation,
151 ajouter la ligne : ::
153 #include CORBA_CLIENT_HEADER(<nom de la classe CORBA>)
155 ``CORBA_CLIENT_HEADER`` est une macro définie dans ``SALOMEconfig.h`` et qui
156 assure l'indépendance des noms de fichiers d'inclusion CORBA par rapport à
157 l'implémentation de CORBA utilisée.
159 #. faire dériver la classe d'implémentation de celle du composant Salome de
163 public POA_Engines::A,
164 public Engines_Component_i {
166 #. définir le (seul) constructeur de la façon suivante dans le fichier d'entête
169 A_impl(CORBA::ORB_ptr orb,
170 PortableServer::POA_ptr poa,
171 PortableServer::ObjectId * contId,
172 const char *instanceName,
173 const char *interfaceName);
175 et dans le fichier d'implémentation C++ (.cxx) : ::
179 PortableServer::POA_ptr poa,
180 PortableServer::ObjectId * contId,
181 const char *instanceName,
182 const char *interfaceName) :
183 Engines_Component_i(orb, poa, contId,
184 instanceName, interfaceName)
187 _id = _poa->activate_object(_thisObj);
190 Ce constructeur sera éventuellement responsable de la création et de
191 l'initialisation de l'objet interne associé au composant CORBA.
193 #. si des structures sont définies par le fichier IDL dans le module Engines,
194 adapter les déclarations des méthodes de la classe d'implémentation.
196 L'exemple ci-dessus illustre les modifications effectuées sur l'exemple 6.
201 Permettre la supervision du composant
202 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
204 Pour pouvoir piloter le composant depuis la supervision, il faut insérer dans
205 chaque service du composant (i.e. dans chaque méthode de la classe
206 d'implémentation qui est appelée lors d'une requète CORBA),
208 * au début, l'instruction : ::
210 beginService(<nom du service>);
212 * à la fin, l'instruction : ::
214 endService(<nom du service>);
216 Ces deux instructions signalent à la supervision de Salomé que le service du
217 composant a bien reçu la requète CORBA (beginService) et que l'exécution du
218 service s'est bien terminée (endService).
221 Mettre beginService et endService
222 dans les méthodes de la classe d'implémentation d'un composant déclare à Salomé
223 que le composant est "supervisable". Ce n'est pas une assurance que l'on pourra
224 utiliser ce composant sans précautions dans le cas où le composant possède un
225 état interne modifié par un ou plusieurs services.
228 On considère un composant ayant une variable interne ``Quantite`` et deux services :
230 * ``S1(x) : Quantite = Quantite + x;`` retourne ``Quantite`` et
232 * ``S2(x) : Quantite = Quantite * x;`` retourne ``Quantite``.
234 Il n'est pas possible *a priori* de connaître la valeur de ``Quantite`` après
235 exécution du graphe de calcul sur la figure suivante.
240 .. image:: images/parallele.png
245 Graphe de calcul contenant des branches parallèles
247 Utilisation de la notification
248 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
250 Pour signaler l'utilisation de la notification (qui provoquera l'ouverture
251 d'une connexion à un canal d'événements), il faut modifier le constructeur de
252 la classe d'implémentation comme suit : ::
256 PortableServer::POA_ptr poa,
257 PortableServer::ObjectId * contId,
258 const char *instanceName,
259 const char *interfaceName) :
260 Engines_Component_i(orb, poa, contId,
261 instanceName, interfaceName, 1)
264 _id = _poa->activate_object(_thisObj);
267 où on a ajouté le paramètre "1" à la fin de l'appel du constructeur de
268 ``Engines_Component_i``. Le composant pourra ensuite utiliser l'instruction
271 void sendMessage(const char *event_type, const char *message);
273 pour envoyer des messages indiquant le déroulement du calcul ou une situation
274 anormale, etc. Ces messages seront visibles de l'utilisateur de Salomé. Le
275 premier paramètre indique le type de message ("warning", "step", "trace",
276 "verbose"), le second paramètre, le contenu (chaîne de caractères) du message.
279 Connexion à l'objet "fabrique" d'un conteneur
280 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
282 Afin de permettre le chargement et l'initialisation d'un composant par un
283 conteneur, il faut fournir une fonction C dont le nom et le code sont imposés :
288 PortableServer::ObjectId * <nom du composant>Engine_factory(
290 PortableServer::POA_ptr poa,
291 PortableServer::ObjectId * contId,
292 const char *instanceName,
293 const char *interfaceName)
295 <classe d'implementation> * O
296 = new <classe d'implementation>(orb, poa, contId,
297 instanceName, interfaceName);
302 ``<nom du composant>`` (ou nom de la classe CORBA, ``A`` ici) et ``<classe
303 d'implementation>`` (``A_impl`` ici) sont spécifiques à chaque composant.
304 Cette fonction est appelée par le conteneur lors du chargement d'un composant.
305 Elle crée un objet CORBA qui réceptionnera les requètes au composant et les
306 transmettra au différents services du composant.
312 Reprenons les fichiers d'implémentation ``alglin_i.hxx`` et ``alglin_i.cxx``
318 .. include:: ./exemples/exemple9/alglin_i.hxx
324 .. include:: ./exemples/exemple9/alglin_i.cxx
328 Classe d'implémentation python
329 ------------------------------
331 **On supposera dans ce paragraphe, que le fichier IDL définit une classe CORBA :
332 B et qu'on utilisera la classe d'implémentation python : B.** La démarche
333 est analogue au cas de l'interface serveur C++ :
336 Mise en conformité avec l'IDL du composant
337 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
339 #. importer la classe du composant de base : ::
341 from SALOME_ComponentPy import *
343 #. faire dériver la classe d'implémentation de celle du composant Salome de
346 class B(Engines__POA.B,
347 SALOME_ComponentPy_i):
349 #. le constructeur de la classe d'implémentation doit débuter par : ::
351 def __init__(self, orb, poa, this, containerName,
352 instanceName, interfaceName):
353 SALOME_ComponentPy_i.__init__(self, orb, poa, this,
354 containerName, instanceName,
358 Permettre la supervision du composant
359 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
361 Pour pouvoir piloter le composant depuis la supervision, il faut insérer dans
362 chaque service du composant (i.e. dans chaque méthode de la classe
363 d'implémentation qui est appelée lors d'une requète CORBA),
365 * au début, l'instruction : ::
367 beginService(<nom du service>);
369 * à la fin, l'instruction : ::
371 endService(<nom du service>);
373 Ces deux instructions signalent à la supervision de Salomé que le service du
374 composant a bien reçu la requète CORBA (beginService) et que l'exécution du
375 service s'est bien terminée (endService). Même remarque que dans le cas C++
379 Utilisation de la notification
380 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
382 Pour signaler l'utilisation de la notification, il faut modifier le
383 constructeur de la classe d'implémentation comme suit : ::
385 def __init__(self, orb, poa, this, containerName,
386 instanceName, interfaceName):
387 SALOME_ComponentPy_i.__init__(self, orb, poa, this,
388 containerName, instanceName,
391 où on a ajouté le paramètre "1" à la fin de l'appel du constructeur de
392 ``SALOME_ComponentPy_i``. Le composant pourra ensuite utiliser l'instruction
395 sendMessage(event_type, message);
397 pour envoyer des messages indiquant le déroulement du calcul ou une situation
398 anormale, etc. Ces messages seront visibles de l'utilisateur de Salomé. Le
399 premier paramètre indique le type de message ("warning", "step", "trace",
400 "verbose"), le second paramètre, le contenu (chaîne de caractères) du message.
406 Reprenons le fichier d'implémentation ``FreeFem.py`` et adaptons le :
409 ``FreeFemComponent.py``
411 .. include:: ./exemples/exemple10/FreeFemComponent.py
415 Utilisation de l'environnement de compilation et d'exécution de Salomé
416 -----------------------------------------------------------------------
418 On utilisera les autotools comme Salomé.
420 Utilisation des structures de données fournies par Salomé ou renvoyées par le composant
421 ---------------------------------------------------------------------------------------
423 Pour cette partie, on se référera aux spécifications CORBA [CORBA]_, et en
424 particulier les spécifications IDL - langages [LANG]_ ou aux différents
425 manuels CORBA, par exemple [HENVIN]_ (C++) et [PyCorba]_ (python).
428 Maillages et champs MED
429 ^^^^^^^^^^^^^^^^^^^^^^^
431 Pour cette partie, on se réfèrera à la documentation de MED et MEDMemory
432 [MEDDoc]_ et [MEDMemory]_.