4 Defining an internal object
5 ===============================
7 .. index:: single: internal object
9 In the remainder of this document, it is assumed that an **internal object** is a **C++ or python object** that provides a
10 first interface to the initial code. The form of this object and communication between the internal object and the
11 initial code will be different depending on the form of the initial code (executable binary, static or dynamic library,
12 f77, C, C++ or python source files).
14 Object methods and attributes
15 --------------------------------
16 In each case, the services and the internal state of the internal object will have to be defined. In particular:
18 * choose the different services of this object
19 * for each service, define input and output data
20 * for each input and each output, define the data type and possibly associated pre-conditions and post-conditions (for example positive input data)
21 * define the internal state of the object and possibly its value before and after the call to different services.
23 **Services** will be implemented in the form of **public methods** and the **internal state** will be implemented in the form of **attributes**.
24 If the designer of the object allows the user to access the attributes in read and write, he must provide services to access these attributes.
26 Fortran77 routines / C functions / C++ classes
27 --------------------------------------------------
30 In the case of Fortran77 routines, C functions and C++ classes, the integrator will simply add a C++ envelope around
31 these functions (see figure :ref:`C++ internal object<figobjetinterne>`), to obtain the internal object.
32 Each method in the object:
34 - extracts information from the input parameters if necessary
35 - calls the internal routine(s) concerned,
36 - formats the results of these internal routines in the output parameters.
41 .. image:: images/objintcpp.png
44 .. centered:: C++ internal object
53 Consider the following f77 fortran routines performing linear algebra calculations on one dimensional floating tables:
57 .. include:: ./exemples/exemple1/addvec.f
63 .. include:: ./exemples/exemple1/prdscl.f
66 and a C++ class simulating a (very) rudimentary vector type:
71 ``vecteur.hxx (C++ interface)``
73 .. include:: ./exemples/exemple1/exec2/vecteur.hxx
77 ``vecteur.cxx (C++ implementation)``
79 .. include:: ./exemples/exemple1/exec2/vecteur.cxx
82 The internal object (i.e. the C++ class) in the example is:
87 .. include:: ./exemples/exemple1/exec2/alglin.hxx
93 .. include:: ./exemples/exemple1/exec2/alglin.cxx
98 #. The integrator chooses methods, parameter transfers and parameter types (in accordance with the requirements of object users).
99 The correspondence between parameters of the internal object and parameters of routines in the initial code is organised
100 by the implementation (file ``alglin.cxx``, above).
101 #. In particular, if MED structures [MED]_ are transferred as input arguments, the C++ implementation file will be required to extract
102 and format information to be transferred to internal calculation routines (in the form of simple and scalar tables for internal
103 fortran routines). For output arguments in the MED format, the implementation will introduce the results of internal routines
104 into the MED objects to be returned.
106 Note the following in the above example:
108 * the ``“C” extern`` declaration in front of C++ prototypes of fortran functions
109 * the “underscore” character added to the C++ name of fortran functions
110 * the mode of transferring arguments, the rule being that pointers will be transferred apart from exceptions (length of
111 character strings). For scalar arguments, the addresses of the scalar arguments will be transferred; for pointer
112 arguments (tables), the pointers will be transferred as is.
114 The internal object can now be used in a C++ code:
116 .. include:: ./exemples/exemple1/exec2/main_extraits.cxx
122 The C / fortran77 encapsulation in a C++ code follows the standard procedure (formats of reals / integers,
123 routine names, transfer of arguments). For example, further information on this subject is given in [ForCpp]_ or [ForCpp2]_.
125 Python function/classes
126 ------------------------
129 The principle of encapsulation of python functions / classes in an internal object (python) is the same as in the previous case
131 .. _figobjetinterne2:
134 .. image:: images/objintpy.png
137 .. centered:: Python internal object
143 An example similar to the previous example starts from Python functions to be encapsulated:
147 .. include:: ./exemples/exemple2/func.py
150 It is easy to integrate these functions into a python class:
155 .. include:: ./exemples/exemple2/compo.py
159 In fact, it is not even necessary to embed python functions of ``func.py``, but it is “cleaner” (particularly if
160 the object has an internal state). The following script uses the Python internal object from a python interpreter:
162 .. include:: ./exemples/exemple2/exmpl.py
166 Initial code in the form of executables
167 --------------------------------------------
170 This case occurs when there are no internal code sources (or when it is not required to integrate these sources
171 into the internal architecture). It will be assumed that the code is in the form of a binary that can be executed
172 by the operating system. Communications can be made with the code.
176 - by one or several files,
177 - by the command line,
178 - using the keyboard to answer questions from the code
180 2. In output, either:
182 - by one or several files,
185 Communication with executables is made using commands (available in C++ and in python):
187 - ``system``: start an executable with which input communications are made through files or the command line, and
188 output communications are made through files,
189 - ``popen``: same functions as the previous case, also with the possibility of retrieving the standard output (screen)
192 The above commands are stored in order of increasing complexity (it is recommended that ``system`` should be used as much as possible).
194 Example 3: Python internal object connected to external executables
195 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
196 It is required to use a “System” object that has 5 services:
198 - ``cd``, that starts from a path (character string) and sets a current directory,
199 - ``cp``, that starts from 2 file names, and copies the first file onto the second in the current directory,
200 - ``touch``, that starts from a file name and updates the date of the file if there is one, and otherwise creates it,
201 - ``rm``, that starts from a file name and destroys the file in the current directory,
202 - ``dir``, that lists the files contained in the current directory.
204 The internal state of the object will be composed of the name of the current directory in which the services of the
205 object (that is set by the ``cd`` service) will work.
207 In Python, the object class could be written:
211 .. include:: ./exemples/exemple3/systeme.py
214 and its use from the python interpreter:
217 .. include:: ./exemples/exemple3/use.py
222 #. This is given as an example, Python has everything necessary in the standard version to perform these services, without
223 the use of system commands (``system`` and ``popen``).
224 #. The example illustrates transfer of input arguments through the command line (names transferred as arguments) and the “capture” of
225 screen outputs from external executables (``system`` that cannot simply recover the standard output from the unix command ``ls``, and
226 in this case ``popen`` is used).
230 Example 4: Internal object connected to an external executable
231 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
232 This example shows a (very) partial interface of a binary executable *FreeFem* [FreeFem]_ in the form of a C++ object.
233 The interface provides access to the definition of a 2D geometry through its boundary, and the approximate resolution of a
234 simple equation (forced convection) on this geometry. The different methods of the internal object are:
236 - a method that records the geometry of the domain,
237 - a method that records the convecting velocity fields,
238 - the calculation method that receives the initial condition (in analytic form – character string), the time step and the number of time steps.
240 The internal state of the object is composed of the geometry and the velocity field.
241 The calculation method creates a file starting from its parameters and the internal state, and then starts a calculation
242 loop (by a system call). The object does not recover the calculation results.
246 #. A complete encapsulation of FreeFem would require far too much effort, this is simply an example.
247 #. We do not retrieve a result in the C++ object in this example (the change is only displayed by the FreeFem internal graphic
248 engine). If it was required to do so, it would be necessary to read the file produced by the external code after the system
249 call, and transfer the results in a form that could be understood by the User of the internal object.
251 Two versions (C++ and python) are listed below.
258 .. include:: ./exemples/exemple4/FreeFem.hxx
264 .. include:: ./exemples/exemple4/FreeFem.cxx
270 .. include:: ./exemples/exemple4/FreeFem.py
273 Use from a C++ code or a python interpreter is similar in the 2 versions:
277 .. include:: ./exemples/exemple4/main.cxx
283 .. include:: ./exemples/exemple4/useFreeFem.py