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