6 ===========================================================
7 Guide for the development of a SALOME module in C++
8 ===========================================================
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.
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.
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
26 - make the component usable in the YACS module.
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::
40 + FindSalomeHELLO.cmake
57 This is done by copying the PYHELLO tree structure, and modifying PYHELLO to HELLO if necessary::
59 cp -r PYHELLO1_SRC HELLO1_SRC
61 mv idl/PYHELLO_Gen.idl idl/HELLO_Gen.idl
62 mv src/PYHELLO src/HELLO
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.
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
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::
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).
84 Finally, we will update the Makefile with the new component name::
86 IDL_FILES = HELLO_Gen.idl
93 The C++ implementation of our CORBA HELLO module (HELLO_Gen idl interface) is made in the src/HELLO directory::
98 The following inclusions are necessary at the beginning of the header of our module (HELLO.hxx)::
100 #include <SALOMEconfig.h>
101 #include CORBA_SERVER_HEADER(HELLO_Gen)
102 #include "SALOME_Component_i.hxx"
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.
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::
115 public POA_HELLO_ORB::HELLO_Gen,
116 public Engines_Component_i
119 HELLO(CORBA::ORB_ptr orb,
120 PortableServer::POA_ptr poa,
121 PortableServer::ObjectId * contId,
122 const char *instanceName,
123 const char *interfaceName);
125 HELLO_ORB::status hello ( SALOMEDS::Study_ptr study, const char* name );
126 HELLO_ORB::status goodbye( SALOMEDS::Study_ptr study, const char* name );
127 void copyOrMove( const HELLO_ORB::object_list& what,
128 SALOMEDS::SObject_ptr where,
129 CORBA::Long row, CORBA::Boolean isCopy );
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.
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::
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);
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)::
150 HELLO_ORB::status HELLO::hello( SALOMEDS::Study_ptr study, const char* name )
155 HELLO_ORB::status HELLO::goodbye( SALOMEDS::Study_ptr study, const char* name )
160 void HELLO::copyOrMove( const HELLO_ORB::object_list& what,
161 SALOMEDS::SObject_ptr where,
162 CORBA::Long row, CORBA::Boolean isCopy )
169 Create and add library to the project::
172 # additional include directories
174 ${KERNEL_INCLUDE_DIRS}
175 ${OMNIORB_INCLUDE_DIR}
176 ${PROJECT_BINARY_DIR}
177 ${PROJECT_BINARY_DIR}/idl
179 # libraries to link to
182 ${KERNEL_SalomeIDLKernel}
184 ${KERNEL_SalomeContainer}
188 # header files / no moc processing
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})
203 Review some of components:
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.
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::
219 runSalome --modules=HELLO -t --pinter --logger --killall
221 We import the LifeCycle module from the Python window, and use its services to load our component into the FactoryServer C++ container::
223 >>> import LifeCycleCORBA
224 >>> lcc = LifeCycleCORBA.LifeCycleCORBA()
226 >>> salome.salome_init()
231 >>> hello = lcc.FindOrLoadComponent("FactoryServer", "HELLO")
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::
239 <HELLO_ORB._objref_HELLO_Gen instance at 0x8274e94>
240 >>> status=hello.hello(salome.myStudy, "Nicolas")
244 The previous commands were grouped in the test function of the /bin/runSalome.py script.
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().
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.
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
269 - src/HELLOGUI/HELLOGUI.h
270 - src/HELLOGUI/HELLOGUI.cxx
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.
276 - src/HELLOGUI/HELLO_msg_en.ts
277 - src/HELLOGUI/HELLO_msg_fr.ts
278 - src/HELLOGUI/HELLO_icons.ts
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
291 This optional directory usually contains different resources files
292 required for the correct operation of SALOME module.
294 - resources/HELLO.png
295 - resources/handshake.png
296 - resources/goodbye.png
297 - resources/testme.png
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.
305 - resources/HELLOCatalog.xml.in
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.
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!
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
340 ======================== ======================== ===================== =============================================================================