Salome HOME
bos #29864 Irrelevant assert in test.
[modules/yacs.git] / doc / cppsalome.rst
1
2 :tocdepth: 3
3
4 .. _cppsalome:
5
6 ===========================================================
7 Guide for the development of a SALOME module in C++
8 ===========================================================
9
10 The purpose of this document is to describe the different steps in the development of a SALOME module in C++.  
11 It follows on from the :ref:`pysalome` document, that documents the PYHELLO module, and it uses the same 
12 approach:  step by step construction of a HELLO module.  Since many points are not repeated, it is recommended 
13 that this document should be read first.
14
15 Steps in the construction of the example module
16 ====================================================
17 The component chosen to illustrate the C++ construction process is the same as the process chosen to illustrate 
18 construction of the Python module:  therefore, it will implement the same Corba idl interface.  It will be 
19 completed by a graphic GUI written in Qt.
20
21 The various steps of the development will be as follows:
22  - create a module structure
23  - create a SALOME component that can be loaded by a C++ container
24  - configure the module so that the component is known to SALOME
25  - add a graphic GUI
26  - make the component usable in the YACS module.
27
28 Creating the module tree structure
29 =======================================
30 We will start by simply putting a SALOME component written in C++ and that can be loaded by a C++ container, into the 
31 example module.  Therefore, all that is necessary is an idl interface and a C++ implantation of the component. 
32 We need to reproduce the following standard file tree structure, to use it in a SALOME module::
33
34   + HELLO1_SRC
35     + CMakeLists.txt
36     + adm_local
37       + CMakeLists.txt
38       + cmake_files
39         + CMakeLists.txt
40         + FindSalomeHELLO.cmake
41     + bin
42       + CMakeLists.txt
43       + VERSION
44       + runAppli.in
45       + runSalome.py
46     + idl
47       + CMakeLists.txt
48       + HELLO_Gen.idl
49     + src
50       + CMakeLists.txt
51       + HELLO
52         + CMakeLists.txt
53         + HELLO.cxx 
54         + HELLO.hxx 
55     + doc
56
57 This is done by copying the PYHELLO tree structure, and modifying PYHELLO to HELLO if necessary::
58
59     cp -r PYHELLO1_SRC HELLO1_SRC
60     cd HELLO1_SRC
61     mv idl/PYHELLO_Gen.idl idl/HELLO_Gen.idl
62     mv src/PYHELLO src/HELLO
63
64
65 IDL interface
66 ==================
67 We modify the HELLO_Gen.idl file in the idl directory:  the defined module is named HELLO_ORB, and the interface 
68 is named HELLO_Gen.  The service provided remains the same:  starting from a character string supplied as the 
69 single argument, a character string derived from the concatenation of “Hello” and the input string is returned.  
70 This service is specified by the hello function.
71
72 A documentation utility based on doxygen has been implemented to compile a documentation of corba services 
73 starting from comments located in idl files. Therefore, we will add few comments to our idl, respecting the 
74 doxygen formalism.  
75 A doxygen comment begins with "/\*" and ends with "\*/".  
76 They are grouped by module or subject, to provide a minimum structure for generated pages.  
77 We will use the following directive in our example::
78
79   \ingroup EXAMPLES
80
81 specifying that the generated documentation forms part of the EXAMPLES group (please refer to 
82 the http://www.doxygen.org site for further information about doxygen).
83
84 Finally, we will update the Makefile with the new component name::
85
86     IDL_FILES = HELLO_Gen.idl
87
88
89 C++ implementation
90 ==================
91 Sources
92 -----------
93 The C++ implementation of our CORBA HELLO module (HELLO_Gen idl interface) is made in the src/HELLO directory::
94
95     HELLO.hxx
96     HELLO.cxx
97
98 The following inclusions are necessary at the beginning of the header of our module (HELLO.hxx)::
99
100     #include <SALOMEconfig.h>
101     #include CORBA_SERVER_HEADER(HELLO_Gen)
102     #include "SALOME_Component_i.hxx"
103
104 The SALOMEconfig.h file contains a number of definitions useful for making the code independent from 
105 the version of CORBA used. SALOME_Component_i.hxx contains the interface of the C++ implementation class 
106 of the SALOME basic component (idl Engines::EngineComponent). Finally, the CORBA_SERVER_HEADER macro 
107 makes inclusion file names independent of the implementation of the CORBA ORB.
108
109 The next step is to define an implementation class called HELLO, derived from POA_HELLO_ORB::HELLO_Gen (abstract class 
110 generated automatically by CORBA during the compilation of the idl) and Engines_Component_i (because 
111 the HELLO_Gen idl interface is derived from Engines::EngineComponent like every SALOME component).  
112 This class contains a constructor whose arguments are imposed by SALOME, a virtual destructor, hello, goodbye and copyOrMove methods providing the required service::
113
114     class HELLO:
115       public POA_HELLO_ORB::HELLO_Gen,
116       public Engines_Component_i
117     {
118     public:
119     HELLO(CORBA::ORB_ptr orb,
120       PortableServer::POA_ptr poa,
121       PortableServer::ObjectId * contId,
122       const char *instanceName,
123       const char *interfaceName);
124     virtual ~HELLO();
125     HELLO_ORB::status hello  ( const char* name );
126     HELLO_ORB::status goodbye( const char* name );
127     void              copyOrMove( const HELLO_ORB::object_list& what,
128                                   SALOMEDS::SObject_ptr where,
129                                   CORBA::Long row, CORBA::Boolean isCopy );
130
131     };
132
133 The hello and goodbye functions use a char* as an argument and return status of the operation.
134 The list of the statuses is defined in the HELLO_Gen.idl, see status enumeration for details.
135
136 Finally, we supply the standard interface of the HELLOEngine_factory function that will be called by the “FactoryServer C++” 
137 to load the HELLO component::
138
139     extern "C"
140     PortableServer::ObjectId * HELLOEngine_factory(CORBA::ORB_ptr orb,
141                                                    PortableServer::POA_ptr poa,
142                                                    PortableServer::ObjectId * contId,
143                                                    const char *instanceName,
144                                                    const char *interfaceName);
145
146
147 The definitions of the constructor and the HELLOEngine_factory instantiation function (both normalized!),
148 hello, goodbye and copyOrMove are given in the source file (HELLO.cxx)::        
149
150         HELLO_ORB::status HELLO::hello( const char* name )
151         {
152         ...
153         }
154
155         HELLO_ORB::status HELLO::goodbye( const char* name )
156         {
157         ...
158         }
159
160         void HELLO::copyOrMove( const HELLO_ORB::object_list& what,
161                                 SALOMEDS::SObject_ptr where,
162                                 CORBA::Long row, CORBA::Boolean isCopy ) 
163         {
164         ...
165         }
166
167 CMakeLists.txt
168 --------------
169 Create and add library to the project:: 
170
171     # --- options ---
172     # additional include directories
173     INCLUDE_DIRECTORIES(
174       ${KERNEL_INCLUDE_DIRS}
175       ${OMNIORB_INCLUDE_DIR}
176       ${PROJECT_BINARY_DIR}
177       ${PROJECT_BINARY_DIR}/idl
178     )
179     # libraries to link to
180     SET(_link_LIBRARIES
181       ${OMNIORB_LIBRARIES}
182       ${KERNEL_SalomeIDLKernel}
183       ${KERNEL_OpUtil}
184       ${KERNEL_SalomeContainer}
185       SalomeIDLHELLO
186     )
187     # --- headers ---
188     # header files / no moc processing
189     SET(HELLO_HEADERS
190       HELLO.hxx
191     )
192     # --- sources ---
193     # sources / static
194     SET(HELLO_SOURCES
195       HELLO.cxx
196     )
197     # --- rules ---
198     ADD_LIBRARY(HELLOEngine ${HELLO_SOURCES})
199     TARGET_LINK_LIBRARIES(HELLOEngine ${_link_LIBRARIES} )
200     INSTALL(TARGETS HELLOEngine EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS})
201     INSTALL(FILES ${HELLO_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS})
202         
203 Review some of components:
204
205 - HELLO_HEADERS contains the header files.
206 - HELLO_SOURCES defines the name of source files
207 - HELLOEngine - library name.
208 - SALOME_INSTALL_LIBS path defines the directories in which library will be install.
209 - Command INCLUDE_DIRECTORIES used to add /bin directories of some modules and packages.
210 - Variable _link_LIBRARIES contains path to libraries of dependent modules and packages.
211
212 Controlling the component from Python (TUI mode)
213 =====================================================
214 When the module is compiled, the lib target of the Makefile in /idl provoked generation of a Python 
215 stub (stub at the customer end generated from the idl and providing an interface in the client language – in this case Python).  
216 Specifically, a HELLO_ORB python module containing a classe_objref_HELLO_Gen is created and used to call services of our 
217 C++ module from Python.  To put this into application, we run SALOME in TUI mode::
218
219     runSalome --modules=HELLO -t --pinter --logger --killall
220
221 We import the LifeCycle module from the Python window, and use its services to load our component into the FactoryServer C++ container::
222
223     >>> import LifeCycleCORBA
224     >>> lcc = LifeCycleCORBA.LifeCycleCORBA()
225     >>> import salome
226     >>> salome.salome_init()
227     createNewStudy
228     []
229     extStudy_1 1
230     >>> import HELLO_ORB
231     >>> hello = lcc.FindOrLoadComponent("FactoryServer", "HELLO")
232
233 HELLO_ORB has to be imported before FindOrLoadComponent is called, so that a typed object can be 
234 returned (“narrowing” operation). Otherwise, the returned object is generic of the 
235 Engines::EngineComponent type.  
236 Let us check that hello object is correctly typed, and we will call the hello service::
237
238     >>> print hello
239     <HELLO_ORB._objref_HELLO_Gen instance at 0x8274e94>
240     >>> status=hello.hello("Nicolas")
241     >>> print status
242     OP_OK
243
244 The previous commands were grouped in the test function of the /bin/runSalome.py script.
245
246 Graphic interface
247 ===================
248 Introduction
249 ----------------
250 To go further with the integration of our module, we will add a graphic interface (developed in Qt) that is 
251 integrated into the SALOME application interface (IAPP).  We will not describe operation of the SALOME IAPP herein, 
252 but in summary, the IAPP manages an event loop (mouse click, keyboard, etc.) and after processing these events 
253 redirects them towards the active module (the principle is that **a single** module is active at a given moment.  
254 When a module is activated, its Graphic User Interface is dynamically loaded).  
255 Therefore the programmer of a module GUI defines methods to process transmitted events correctly.  
256 The most important of these events are OnGUIEvent(), OnMousePress(), OnMouseMove(), OnKeyPress(), DefinePopup(), CustomPopup().
257
258 Strictly speaking, the GUI library is optional for each SALOME module.
259 In some cases it's enough to implement CORBA engine only. Then,
260 the services of the module will be avaiable in a CORBA environment.
261 The module can be loaded to the SALOME container and its services
262 can be used in the SALOME supervision computation schemas, in Python
263 scripts or/and in C++ implementation of other modules.
264
265 A GUI library is necessary only if it is planned to access the module
266 functionality from the SALOME GUI session via menu actions, dialog boxes
267 and so on. 
268
269 - src/HELLOGUI/HELLOGUI.h
270 - src/HELLOGUI/HELLOGUI.cxx
271
272 These files provide the implementation of a GUI library of
273 the HELLO module. In particular, these files specify menus, toolbars,
274 dialog boxes and other such staff.
275
276 - src/HELLOGUI/HELLO_msg_en.ts
277 - src/HELLOGUI/HELLO_msg_fr.ts
278 - src/HELLOGUI/HELLO_icons.ts
279
280 These files provide a description (internationalization) of GUI
281 resources of the HELLO module. HELLO_msg_en.ts provides an English
282 translation of the string resources used in a module (there can be also
283 translation files for other languages, for instance French; these files
284 are distinguished by the language suffix). HELLO_icons.ts
285 defines images and icons resources used within the GUI library of
286 HELLO module. Please refer to Qt linguist documentation for more
287 details.
288
289 - resources
290
291 This optional directory usually contains different resources files
292 required for the correct operation of SALOME module.
293
294 - resources/HELLO.png
295 - resources/handshake.png
296 - resources/goodbye.png
297 - resources/testme.png
298
299 These are different module icon files. HELLO.png file provides main icon
300 of HELLO module to be shown in the SALOME GUI desktop. Other files are
301 the icons for the functions implemented by the module; they are used
302 in the menus and toolbars.
303
304
305 - resources/HELLOCatalog.xml.in
306
307 The XML description of the CORBA services provided by the HELLO
308 module. This file is parsed by SALOME supervision module (YACS) to generate
309 the list of service nodes to be used in the calculation schemas. The
310 simplest way to create this file is to use Catalog Generator utility
311 provided by the SALOME KERNEL module, that can automatically generate
312 XML description file from the IDL file. In GUI, this utility is available
313 via the Tools main menu.
314
315
316
317
318 Syntax naming rules
319 =============================
320 A number of naming rules were used in the above description.  This chapter gives more details about these rules.  
321 They are not all compulsory, but they make it easy to understand the program if they are respected!
322
323 ======================== ======================== ===================== =============================================================================
324   Rules                    Formalism                HELLO example              Comment                               
325 ======================== ======================== ===================== =============================================================================
326  Module name              <Module>                HELLO                 This is the name that appears in the modules catalog
327  CVS base                 <Module>                EXAMPLES              If the cvs base contains several modules, another name will be used.
328  Source directory         <Module>_SRC            HELLO1_SRC            Index 1 is used because several versions of the module are provided.
329  Idl file                 <Module>_Gen.idl        HELLO_Gen.idl 
330  CORBA module name        <Module>_ORB            HELLO_ORB             Avoid the use of the module name (conflicts)
331  CORBA interface name     <Module>_Gen            HELLO_Gen             The idl compilation generates an abstract class POA_<Module>_ORB::<Module>_Gen
332  Source file              <Module>.cxx            HELLO.cxx             In the /src/<Module> directory
333  Implementation class     <Module>                HELLO                 This class inherits from POA_HELLO_ORB::HELLO_Gen
334  Instantiation function   <Module>_Engine_factory HELLO_Engine_factory  This function is called by the SALOME Container
335  Modules catalog          <Module>Catalog.xml     HELLOCatalog.xml      In /resources
336  C++ library name         lib<Module>Engine       HELLO-Engine          In the /src/<Module> directory
337  GUI C++ name             lib<Module>GUI          libHELLOGUI           In the /src/<Module>GUI directory
338  Environment variable     <Module>_ROOT_DIR…      HELLO_ROOT_DIR  
339  ...                      ...                      ...                   ...                                   
340 ======================== ======================== ===================== =============================================================================
341