Salome HOME
bos #26458 Versioning of sources via git commit id (sha1)
[modules/yacs.git] / doc / hxx2salome.rst
1
2 .. _hxx2salome:
3
4 hxx2salome : a SALOME component generator
5 ==========================================
6
7
8
9 This document is the following of the HELLO component documentation [R1]_, which presented the basis for the implementation of a SALOME Component, and the CALCULATOR component documentation [H1]_, which introduced the use of MED within the SALOME context. These two examples showed that implementing a SALOME component doesn't require much imagination, it can be done by following some predefined rules. Thus, it is possible, provided a C++ standalone component, to wrap it into a SALOME Component automatically. This document presents hxx2salome, a prototype tool for automatic SALOME Component generation. This tool starts from the interface of a C++ component (an .hxx file), parse the public  API , and use the type information to generate the SALOME component (the  IDL  interface, and its implementation).
10
11 Getting started
12 ---------------
13
14 In this chapter, we will create from scratch a new SALOME component that add and multiply integers, and compute a factorial. We suppose that  hxx2salome  (and the related tools  SA_new_component  and  SA_build ) have been installed in a directory called  $HXX2SALOME_ROOT_DIR , which is present in your  $PATH .
15
16 C++ component implementation
17 ''''''''''''''''''''''''''''
18
19 The first thing to do is to implement the C++ engine that will perform the services. To do it, we use the  SA_new_cpp_component  tool:
20
21
22
23 ::
24
25     
26     $ SA_new_cpp_component  CALC
27     $ ls CALC_CPP_SRC/
28     adm  archive  AUTHORS  build_configure  ChangeLog  configure.in.base
29     Makefile.am  NEWS  README  rfind  root_clean  src
30     
31
32
33
34
35 The   SA_new_cpp_component CALC  command has created a complete tree in directory  CALC_CPP_SRC  that allow you to build a C++ component with a  SWIG  python interface. Now we have to define the interface and implement it. For that, we edit and adapt the templates that have been generated in the source directory:
36
37
38
39 ::
40
41     
42     $ cd CALC_CPP_SRC/src/CALC/CALC_CXX  # go in source dir
43     $ vi CALC.hxx  # edit interface template and adapt it
44     
45     #ifndef _CALC_HXX_
46     #define _CALC_HXX_
47     
48     class CALC
49     {
50     public:
51         unsigned fact(unsigned n);
52         int add(int n1, int n2);
53         int mul(int n1, int n2);
54     };
55     
56     #endif
57     
58     $ vi CALC.cxx # edit and adapt class implementation template
59     
60     #include "CALC.hxx"
61     
62     int CALCUL::add(int i1, int i2)
63     {
64         return i1+i2;
65     }
66     
67     int CALCUL::mul(int i1, int i2)
68     {
69         return i1*i2;
70     }
71     
72     unsigned CALCUL::fact(unsigned n)
73     {
74         unsigned fact=1;
75         for (unsigned i=n; i!=1; --i)
76             fact*=i;
77         return fact;
78     }
79     
80
81
82
83
84 A template python test file was also generated, that can be callable both from python and from SALOME. You can if you wish edit it and add the tests you want:
85
86
87
88 ::
89
90     
91     $ cd ../CALC_TEST
92     $ vi CALC_test.py
93     
94     from os import getenv
95     if getenv("SALOMEPATH"):
96         import salome
97         import CALC_ORB
98         my_CALC = salome.lcc.FindOrLoadComponent("FactoryServer", "CALC")
99         IN_SALOME_GUI = 1
100     else:
101         import CALCSWIG
102         my_CALC=CALCSWIG.CALC()
103     pass
104     #
105     #
106     print "Test Program of CALC component"
107     print "5 + 3 = ", my_CALC.add(5,3)
108     print "5 * 3 = ", my_CALC.mul(5,3)
109     print "5! = ", my_CALC.fact(5)
110     
111
112
113
114
115 Only the last three lines were added, the beginning is part of generated template.
116
117 Compilation – Testing with python
118 '''''''''''''''''''''''''''''''''
119
120 It's time now to compile the component and test it. The component is built under Automake. The build procedure (build_configure, configure, make, make install) is explained in the  README  file. You can also use the  SA_build  tool:
121
122
123
124 ::
125
126     
127     $ cd ../../../..   # go in father directory of CALC_CPP_SRC
128     $ SA_build CALC_CPP_SRC
129         ...
130     $ ls
131     CALC_CPP_BUILD  CALC_CPP_INSTALL  CALC_CPP_SRC
132     
133     $ ls  CALC_CPP_INSTALL  # check installation was done
134     bin  include  lib
135     
136     # update pathes for component's use within python
137     $ setenv PYTHONPATH \
138     instalDir/bin/salome:instalDir/lib/salome:$PYTHONPATH   
139     $ setenv LD_LIBRARY_PATH \
140     instalDir/lib/salome:$LD_LIBRARY_PATH 
141     
142     $ python   # test component with python
143     >>> import CALC_test
144     Test Program of CALC component
145     5 + 3 =  8
146     5 * 3 =  15
147     5! = 120
148
149
150
151
152 Before testing the component from python, it was necessary to update  LD_LIBRARY_PATH  and  PYTHON_PATH  environment variables.
153
154 SALOME component generation
155 '''''''''''''''''''''''''''
156
157 The C++ engine is finished, and tested - the final step is the integration inside SALOME. This is done  using  hxx2salome  tool (the options used here are explained in Chapter 8.2 – the tool also has a graphical interface):
158
159
160
161 ::
162
163     
164     hxx2salome -c -e ${INTEGRATION_ROOT}/my_env_products.sh instalDir/CALC_CPP_INSTALL \
165                 CALC.hxx libCALCCXX.so ${INTEGRATION_ROOT}
166        ...
167     $ source ${INTEGRATION_ROOT}/my_env_products.sh
168     $ runSalome –-modules=CALC   # launch salome with CALC compo
169     
170     >>> import CALC_test  # import test case from python console
171
172
173
174
175 The component can now be used inside SALOME, from the python embedded console, or from Supervision.
176
177
178
179 What is a C++ component?
180 ------------------------
181
182 We explain in this paragraph what is meant by “C++ component” in this document. This definition is definitely not unique!
183
184 Let's first try to define more generally what components are. They are used to deliver reusable, “off-the-shelf” software unit for incorporation into large applications (such as frameworks) : a component can be deployed independently and is subject to third-party composition. Its aim is to improve efficiency for end-users. It has specified interfaces and explicit context dependencies only.   It encapsulates small-scale abstractions within a given domain.
185
186 A C++ component is a “high level” unit of reuse, based upon some source code libraries (developed in FORTRAN, C or C++). It takes the form of a C++ class. Its interface is the public API of this class, and is declared in an include file. It is designed to  collaborate  with other components . Therefore its API emphasizes the logical chains of computation a user can perform, and the data that may be exchanged with external world conform to standards (for example in the SALOME context: basic types, MED types and XDATA types).
187
188 For being more concrete, let's take the (simple) example of a steady-state neutronic component developed by CEA to work in collaboration with thermal-hydraulic and fuel-pin mechanics components. The interface of this component is:
189
190
191
192 ::
193
194     
195      class CoreComponent
196     {
197     public:
198         void start();
199         void end();
200         void compute_power(int nitermax=200,
201                            double epsflux=1e-4,
202                            double espeigenvalue=1e-4);
203         const MEDMEM::MESH& DKCore_get_mesh();
204         const MEDMEM::FIELD<double>* get_power();
205         void feedback(const MEDMEM::FIELD<double>& Tcomb,
206                       const MEDMEM::FIELD<double>& Dmod);
207     }
208     
209
210
211
212
213 It emphasizes the following chain of computation:
214
215
216
217
218
219
220
221
222
223 .. image:: images/10000000000003210000012BF34ED8EC.png
224    :align: center
225
226
227
228
229
230
231
232
233
234
235
236
237
238 It is designed to exchange MED objects: export of the mesh used for computation, and the neutronic power field, and import of fuel temperature and moderator density fields for thermal-hydraulic feedback.
239
240 This component was implemented with a preexisting function library, that was used in a neutronic software context. The internal format for meshes and fields was converted in MED format for exchange purpose.
241
242
243
244 SALOME component architecture (insights)
245 ----------------------------------------
246
247 The SALOME component architecture is based on  CORBA , and has been optimized for big data transfers. The key points of the architecture are:
248
249 * Distributed components with the appearance of proximity. There is no difference between local and distant objects, the network exchanges are done by the  CORBA  bus, or MPI or any other protocol, everything being totally transparent for the end user, who just has to call methods on his “apparently local” objects.
250
251
252
253 * Heterogeneities are hidden by  CORBA , which is multi-language and multi-platform!
254
255
256
257 * An open architecture, object oriented, facilitating evolutions and integration of new components.
258
259
260
261 * On top of the  CORBA  layer has been developed a specialized layer ( KERNEL ), which offers services like management of the components and their life cycle, persistence of  objects, resource management, logs and notification, supervision, and GUI .
262
263
264
265 * A common normalized data format for meshes an fields ( MED ), which facilitates exchanges between components and integration in the platform.
266
267
268
269
270 The components are usually developed with C++ or python – but this is not an obligation. For components based upon a C-compatible library of functions (Fortran, C, C++, ...), the proposed architecture is the following :
271
272
273
274 .. image:: images/100000000000030C00000270AD87A128.png
275   :align: center
276
277 The low level libraries are wrapped in a high level C++ component, that is exported to Python using SWIG, and for distribution and coupling to SALOME using hxx2salome. Same scripts can be use in Python or within SALOME.
278
279
280
281
282
283 SALOME Component generation
284 ---------------------------
285
286 In this chapter, we explain briefly the approach used to pass from a C++ component (as described in chapter 1) to a SALOME component.
287
288 A SALOME component is defined by its IDL interface (as explained in ...). It is then implemented using a target language, for example C++ (this step is called the IDL to C++ mapping).
289
290 Here we are doing the opposite! We have a C++ component with its interface (the definition of a class in a header), and we want to get a SALOME component (with its IDL interface, implemented using the C++ component). For doing this, we have to invert the IDL to C++ mapping. This is not feasible in a most general way (because of course user-defined C++ types don't have their counterpart in IDL). But if we restrict the C++ type to the mapping of the  IDL  types supported by SALOME, then we have a way to go back from C++ to IDL .
291
292 The operations performed for the SALOME component generation are summed up in the following figure:
293
294
295
296 .. image:: images/1000000000000321000002300A9186FC.png
297   :align: center
298   :height: 10.749cm
299
300
301
302 After these operations, the generated files are inserted in a template SALOME module (basically a clone of the  CALCULATOR  component described in ...). We obtain that way a full module ready for compiling.
303
304 IDL definition
305 --------------
306
307 The   IDL  code generation is based upon the type analysis of the C++ public  API . Of course, generation can be done only if there is a  CORBA  equivalent type. This is the case for all basic types. It is also the case for the  MED  types, because a  CORBA  level was developed ( MESH ,  SUPPORT  and  FIELD  interfaces), and a Client level that allow to create local C++  MED  objects from  CORBA  objects. This last point is important for code generation, because it simplify it greatly! (The only thing to do is to create a client object and pass it to the C++  API ). The last supported types are vectors, they are treated using the Sender/Receiver mechanism of SALOME, thus optimizing the data transfer.
308
309 Correspondance for parameters
310 '''''''''''''''''''''''''''''
311
312 The following table resume all the supported C++ types for parameters,  and the associated IDL type:
313
314 =========================================== ============================= 
315  *C++ Argument type*                        *IDL associated type*       
316 =========================================== ============================= 
317  int                                        in long                     
318  double                                     in double                   
319  float                                      in float                    
320  long                                       in long                     
321  short                                      in short                    
322  unsigned                                   in unsigned long            
323  const char*                                in string                   
324  const std::string&                         in string                   
325  int&                                       out long                    
326  double&                                    out double                  
327  long&                                      out long                    
328  short&                                     out short                   
329  float&                                     out float                   
330  unsigned&                                  out unsigned long           
331  std::string&                               out string                  
332  const MEDMEM::MESH&                        in SALOME_MED::MESH         
333  const MEDMEM::MESH*                        in SALOME_MED::MESH         
334  const MEDMEM::SUPPORT&                     in SALOME_MED::SUPPORT      
335  const MEDMEM::SUPPORT*                     in SALOME_MED::SUPPORT      
336  const MEDMEM::FIELD<double>*               in SALOME_MED::FIELDDOUBLE  
337  const MEDMEM::FIELD<double>&               in SALOME_MED::FIELDDOUBLE  
338  const std::vector<double>&                 in SALOME::SenderDouble     
339  std::vector<double>*&                      out SALOME::SenderDouble    
340  const std::vector< std::vector<double> >&  in SALOME::Matrix           
341  MEDMEM::FIELD<double>*&                    out SALOME_MED::FIELDDOUBLE 
342  const MEDMEM::FIELD<int>*                  in SALOME_MED::FIELDINT     
343  const MEDMEM::FIELD<int>&                  in SALOME_MED::FIELDINT     
344  const std::vector<int>&                    in SALOME::SenderInt        
345  std::vector<int>*&                         out SALOME::SenderInt       
346  MEDMEM::FIELD<int>*&                       out SALOME_MED::FIELDINT    
347 =========================================== ============================= 
348
349
350 As we can see,  **it is very important to take great care of the qualifiers used in the C++ interface**  because they are interpreted. The determination of the  ``in/out``  qualifier of  ``IDL``  parameters is based upon the  ``const``  and reference qualifier of C++ parameters. Basic types (passed by value in C++) are considered in parameters, references to basic types are considered out parameters. For user defined types, the  ``const``  qualifier is interpreted as in parameter, and reference to pointer as out parameter.
351
352 For simplification purpose, SALOME doesn't allow the use of  ``IDL inout``  parameters. For this reason,  **non const pointers or references are not treated** .
353
354 Correspondance for returned type
355 ''''''''''''''''''''''''''''''''
356
357 The mapping between C++ returned types and their IDL counterpart is similar, except that we don't have to care about in/out qualifier! (The const and reference qualifier don't discriminate IDL type, but this information will nevertheless be useful when generating IDL implementation for memory management).
358
359
360
361 ==================================== ========================= 
362  *C++ returned type*                 *IDL associated type*   
363 ==================================== ========================= 
364  void                                void                    
365  int                                 long                    
366  double                              double                  
367  float                               float                   
368  long                                long                    
369  short                               short                   
370  unsigned                            unsigned long           
371  const char*                         string                  
372  char*                               string                  
373  std::string                         string                  
374  const MEDMEM::MESH&                 SALOME_MED::MESH        
375  MEDMEM::MESH&                       SALOME_MED::MESH        
376  const MEDMEM::MESH*                 SALOME_MED::MESH        
377  MEDMEM::MESH*                       SALOME_MED::MESH        
378  MEDMEM::SUPPORT*                    SALOME_MED::SUPPORT     
379  const MEDMEM::FIELD<double>*        SALOME_MED::FIELDDOUBLE 
380  const MEDMEM::FIELD<double>&        SALOME_MED::FIELDDOUBLE 
381  MEDMEM::FIELD<double>*              SALOME_MED::FIELDDOUBLE 
382  MEDMEM::FIELD<double>&              SALOME_MED::FIELDDOUBLE 
383  std::vector<double>*                SALOME::SenderDouble    
384  const MEDMEM::FIELD<int>*           SALOME_MED::FIELDINT    
385  const MEDMEM::FIELD<int>&           SALOME_MED::FIELDINT    
386  MEDMEM::FIELD<int>*                 SALOME_MED::FIELDINT    
387  MEDMEM::FIELD<int>&                 SALOME_MED::FIELDINT    
388  std::vector<int>*                   SALOME::SenderDouble    
389  std::vector<std::vector<double> >*  SALOME::Matrix          
390 ==================================== ========================= 
391
392
393
394 Example
395 '''''''
396 To finish, let's have a look on the IDL generated module corresponding to our neutronic component example:
397
398
399
400 ::
401
402     module CoreComponent_ORB
403     {
404       interface CoreComponent_Gen : Engines::EngineComponent,
405                                     SALOME::MultiCommClass
406       {
407            void start();
408            void end();
409            void compute_power(in long nitermax,
410                               in double epsflux,
411                               in double espeigenvalue);
412            SALOME_MED::MESH get_mesh();
413            SALOME_MED::FIELDDOUBLE get_power();
414            void set_feedback(in SALOME_MED::FIELDDOUBLE Tcomb,
415                              in SALOME_MED::FIELDDOUBLE Dmod);
416       };
417     };
418
419
420
421
422 IDL Implementation
423 ------------------
424
425 As explained in [R2]_ and [H2]_, the  IDL  implementation consists in writing a servant (an object that will perform the IDL contract). The source of this servant is composed in two files, named in SALOME by convention  <module_name>.hxx  and  <module_name>.cxx . The generated code for these two files is also based upon the type analysis of the C++ public  API  : for each C++ type, we know the  IDL  type that was associated (cf. Chapter 4), and consequently the code to generate. This code follows always the same scheme. We first generate the header  <module_name>.hxx , which contains the class declaration of the servant, and is imposed by the rules of the C++ mapping of CORBA.  We then generate  <module_name>.cxx, which contains the class definition. For each method, we proceed in three steps :
426
427 * Arguments processing : conversion of the types imposed by C++ mapping rules to the type of the C++ component. Of course, this conversion is always possible, because we have restricted the C++ component type to the one for which this operation is possible!
428
429
430
431 * Call of the C++ component : the call is performed with the converted types of step 1.
432
433
434
435 * Post treatment of the returned argument : This operation is the opposite of first step : the type of the parameters returned by the C++ component are converted to match the  C++ mapping rules.
436
437
438
439 This being abstract, let's examine the generated code for two of the CoreComponent example :
440
441
442
443 ::
444
445     const MEDMEM::FIELD<double>* get_power();
446     void feedback(const MEDMEM::FIELD<double>& Tcomb,
447                   const MEDMEM::FIELD<double>& Dmod);
448
449
450
451
452 IDL:
453
454 ::
455
456            SALOME_MED::FIELDDOUBLE get_power();
457            void set_feedback(in SALOME_MED::FIELDDOUBLE Tcomb,
458                              in SALOME_MED::FIELDDOUBLE Dmod);
459     
460
461
462 CoreComponent_i.hxx:
463
464 ::
465
466     
467     
468         SALOME_MED::FIELDDOUBLE_ptr get_power();
469       
470         void set_feedback(
471             SALOME_MED::FIELDDOUBLE_ptr Tcomb,
472             SALOME_MED::FIELDDOUBLE_ptr Dmod);
473     
474
475
476 CoreComponent_i.cxx:
477
478 ::
479
480     
481     SALOME_MED::FIELDDOUBLE_ptr DKCORE_i::get_power()
482     {
483         beginService("DKCORE_i::get_power");
484         BEGIN_OF("DKCORE_i::get_power");
485     //  Call cpp component
486         const MEDMEM::FIELD<double>* _rtn_cpp=cppCompo_->get_power();
487     //  Post-processing & return
488         MEDMEM::FIELDDOUBLE_i* _rtn_field_i=new MEDMEM::FIELDDOUBLE_i(
489         const_cast<MEDMEM::FIELD<double>*>(_rtn_cpp),false);
490         SALOME_MED::FIELDDOUBLE_ptr _rtn_ior = _rtn_field_i->_this();
491         endService("DKCORE_i::get_power");
492         END_OF("DKCORE_i::get_power");
493         return _rtn_ior;
494     }
495     
496     void DKCORE_i::set_feedback(
497         SALOME_MED::FIELDDOUBLE_ptr Tcomb,
498         SALOME_MED::FIELDDOUBLE_ptr Dmod)
499     {
500             beginService("DKCORE_i::set_feedback");
501             BEGIN_OF("DKCORE_i::set_feedback");
502     //      Arguments processing
503             MEDMEM::FIELDClient<double> _Tcomb(Tcomb);
504             MEDMEM::FIELDClient<double> _Dmod(Dmod);
505     //      Call cpp component
506             cppCompo_->set_feedback( _Tcomb, _Dmod);
507     //      Post-processing & return
508             endService("DKCORE_i::set_feedback");
509             END_OF("DKCORE_i::set_feedback");
510     }
511
512
513
514
515 The IDL generated part is driven by the tables given in Chapter 5.1 and 5.2.  You can check for example that   in SALOME_MED::FIELDDOUBLE  correspond in table 5.1 to C++ type  const MEDMEM::FIELD<double>&.
516
517 The  CoreComponent_i.hxx  interface is imposed by the CORBA norm (C++ mapping).
518
519 Finaly, the implementation of methods in  CoreComponent_i.cxx  is done in three steps. First step is argument processing : we convert the  Corba  types in order to call the C++ component. In set_feedback method, this consists in creating  FIELDClient  from the  received  FIELDDOUBLE_ptr . Second step is the call of C++ component method with converted types of step 1. Last step is to create  Corba  returned types from the types returned bu C++.  In get_power method, we wrap the returned  const MEDMEM::FIELD<double>*  in a  Corba  field  FIELDDOUBLE_ptr  .
520
521 A last word about memory management. The Corba field created in get_power method doesn't take ownership of the C++ field it wrap (false parameter in the constructor).  This is due to the fact that the C++ component method return a  **const**  field, thus indicating it owns the returned field. With a non const field, the Corba field would have get ownership (true parameter passed to the constructor), which means that deletion of Corba field causes deletion of C++ field).
522
523
524
525
526
527 Usage
528 -----
529
530 Installation
531 ''''''''''''
532
533 The generator is a script file called  hxx2salome , written in bash, which manages:
534
535 * the code generation,
536
537
538
539 * the compilation of generated module,
540
541
542
543 * the update of SALOME environment file.
544
545
546
547 This script can be used without any compilation. A Graphical User Interface, named ghx2salome was developed (with Qt) to wrap the script, which need to be installed and compiled:
548
549
550
551 ::
552
553       
554       cd <absolute path of HXX2SALOME>
555       ./build_configure
556       ./configure --prefix=<absolute path of HXX2SALOME>
557       make
558       make install
559     
560
561
562
563
564 After installing, you have to set the environment variable  HXXTOSALOME_ROOT_DIR  to the bin directory that was installed and contains the  hxx2salome, SA_new_cpp_component, SA_build  scripts and the  ghx2salome  binary:
565
566
567
568 ::
569
570     setenv HXX2SALOME_ROOT_DIR=<absolute path of HXX2SALOME>/bin
571
572
573
574
575 You may finally also configure the hxx2salome script (it is not mandatory, but may facilitate usage). For configuring the script, you can set the two following variables defined at the beginning :
576
577 * ENVIRON_FILE  : SALOME environment file used for compilation. If present, hxx2salome will propose to compile new module (by sourcing  ENVIRON_FILE  file, and executing build_configure, configure, make & make install). It will also update this file with the new environment variable necessary to run generated module. This environment file can also be passed using  **-e**  option.
578
579
580
581
582 * CONFIGURE_OPTION  : options passed to configure (for example  --disable-debug  or  --enable-production  ). This one cannot be passed by argument to the script. Default is no option.
583
584
585
586
587
588
589 Running the script
590 ''''''''''''''''''
591 The command to run the script is  (supposing  HXX2SALOME_ROOT_DIR  is in your  PATH ) :
592
593
594
595 ::
596
597     hxx2salome [OPTIONS] CPPdir CPP.hxx libCPP.so SALOMEdir
598
599
600
601
602 where the mandatory components are:
603
604 * CPPdir  : the installation directory (absolute path) of the c++ standalone component,
605
606
607
608 * CPP.hxx  : the header name of the component,
609
610
611
612 * libCPP.so  : the name of the shared library.
613
614
615
616 * SALOMEdir  : the directory where you want to install generated SALOME component.
617
618 (Of course,  CPP.hxx  and  libCPP.so  have to be found in  CPPdir )
619
620
621
622 In addition, you can use following options to transmit information to generator:
623
624 **-c**  : to compile the component after code generation,
625
626 **-l** : to launch SALOME with the component after compilation,
627
628 **-e**  : environment_file  : to specify an SALOME environment file to source (for compiling)
629
630
631
632 The script gives user information on what have been done (checking of arguments, extraction of public function, which public function is compatible or not, the generated IDL, ...) to allow to check validity.
633
634 Running the GUI
635 '''''''''''''''
636
637 The GUI allow you to select the arguments with a file browser – thus avoiding spelling mistakes in file names that cause script abortion. The command to start the GUI is  **gxx2salome** . It launch the following window :
638
639
640
641 .. image:: images/100000000000021500000199FE12879E.png
642   :align: center
643
644
645
646
647
648 Limitations – Advice
649 ---------------------
650
651 * The standalone C++ component should have a default constructor (a constructor without arguments). This is because there is no mechanism to transmit arguments from SALOME to a user-defined component. If your component needs information to be valid, you have to split construction and initialization, by adding a method that does initialization.
652
653
654
655 * Only methods with compatible types (types listed in Chapter 5, for which a conversion from CORBA to C++ is available) are treated. If a method contains non compatible types, it is just ignored (it is not blocking, you'll just get a SALOME component without the non compatibles methods).
656
657
658
659 * Avoid inline functions inside the header. They are not treated! If you have inlined functions in your header, you can remove them – or create a clone of your header only for generation purpose, without inline functions.
660
661
662
663 * The name of the C++ component (the name of the class), which provide the name of the SALOME component, should be uppercase. This strange limitation is due to SALOME.
664
665
666
667 * Typedef in the header are prohibited!
668
669
670
671 * The const qualifiers should be carefully analyzed, it impact the way SALOME will manage memory. The critical case is if you have an internal field, and you (wrongly) return a non const pointer on it. Because the pointer is non const, it is considered that the SALOME component takes ownership of the field, and consequently will delete it after usage – thus invalidating an internal pointer of your C++ component. Crash is the most frequent issue of this case...
672
673
674
675 * Avoid including headers in your component interface. Use as much as possible forward declaration. This common C++ rule will reduce the dependencies and fasten compilation. The side effect for the generator is that if you include headers in your component interface  you'll have to indicate to the generator the paths where to find these included files.
676
677
678
679 * Avoid “using namespace” instruction in header (common C++ rule). MED and XDATA types should figure with the resolution operator. The generator doesn't recognize types if the namespace is not specified.
680
681
682
683
684
685
686 .. [H1] The MED Calculator component (N. Crouzet) (see :ref:`calculator`).
687
688 .. [H2] Integration of components into the SALOME environment (M. Tajchman) (see :ref:`components`)
689