We present here how the modules are organized and which rules we follow to develop the B++ Library. We think it will be useful to people who want to understand the source code of the library or want to extend the library.
A module can be written in C++ or in Java. For C++, a module is associated with a header file (*.hpp ) and eventually a source file (*.cpp ). The header file is the interface of the module and the source file is its implementation. For Java, a module is associated only with a source file (*.java ). This file is both the interface and the implementation of the module. If a Java module has to interact with a C++ module, its C++ representation must be generated in the module Jirk (cf. the section on ).
The modules are organized in a hierarchy, i.e. a module can contain other modules. So, with each module is eventually associated a folder that contains the files (*.cpp , *.hpp and *.java ) of its submodules. For instance, the Standard module contains the two modules called Maths and Stream . The Maths module also contains three modules called Complex , Integer and Real . The hierarchy of the source files can be:
standard.hpp
standard.cpp
standard
maths
complex.hpp
complex.cpp
integer.hpp
integer.cpp
real.hpp
real.cpp
maths.hpp
maths.cpp
Stream.java
The modules of the B++ Library are contained in the sources folder. In sources/bpp are the modules more specific to the B++ Library and in sources/jirk is the C++ representation of Java classes.
With Java, the modules are organized in packages. It is a feature Java provides naturally. Hence to access an element of a package you must specify the name of the package before the name of the element. The same way with C++, the elements of a module are encapsulated in a namespace, except the macrocommands. For instance, the swap function of the Standard module is called the following way: standard::swap( ...) . However the new_object macrocommand of the Standard module is called by: new_object( ...) . That means macrocommands defined in the B++ Library (like new_object ) can not be redefined, but the other elements of the B++ Library (like the swap function) can be redefined without creating any overload or any ambiguity.
In the B++ Library, the modules are organized in a hierarchy. The namespace associated with a module is built by enumerating the path in the hierarchy to access the module. For instance, the Integer module part of the Maths module, also contained in the Standard module, is referred as the Standard/Maths/Integer module and its namespace is standardMathsInteger .
Finally, a module can "integrate" another module. That means all the elements of the integrated module can be used directly as elements of the integrating module. For instance, if the Graph module integrates the Standard module, the swap function of the Standard module can be used as Graph::swap .
|
INITIALIZATION AND TERMINATION |
|
Any C++ module that contains global variables, global constants or class attributes needs an "initializer". This is an object inherited from the standardInitializer::clInitializer superclass. This object has two methods start and stop . The start method must be called before the first use of any element of the module. In the same way, the stop method must be called after the last use of any element of the module.
Before using the library, the user only has to call the function standard::openLibrary to initialize all the modules he/she needs. And after using the library, the user has to call the function standard::closeLibrary to terminate the modules.
These two functions control the sequence of initialization and termination of the C++ modules according to their dependency. The following rule is used in B++ Library. Any global constant, global variable or class attribute that belongs to a class must be a pointer. In the start method of the initializer, the object will then be allocated and initialized. Finally it will be destructed in the stop method of the same initializer. However, a global constant, a global variable or a class attribute that belongs to a type (enumeration, integer...) can be directly an object. In the start method of the initializer, the object will simply be initialized.
A user of the B++ Library also has to avoid global objects when using elements of the library. Because static elements are initialized before the main function and unfortunately, the library can not be initialized before. If the user really needs global objects, we advise him/her to follow the rule above.
The reason of such mechanism and rule is that the control of the sequence of initialization of the global constants, global variables and class attributes can not be done directly with C++. For more details, look directly at the source code of a module like Standard/Ascii in the B++ Library. With Java, the sequence of initialization of the modules is done logically according to the dependency of the modules.
|
NOTATIONS AND CONVENTIONS |
|
In order to avoid the collision of names between elements of the library, we use conventions to name them. Except for the namespaces, the functions and the methods, all the names of the library have a prefix. Here is their significance.
ty... |
Means the element is a variable type (an element defined with it can be modified). |
tc... |
Means the element is a constant type (an element defined with it can not be modified). |
cl... |
Means the element is a class (an object defined with it can be modified). |
ct... |
Means the element is a constant class (an object defined with it can not be modified). |
cp... |
Means the element is a virtually instantiated class (the parameters of the class have been defined but the class is still not instantiated). For instance, in the function template <class prType> function(void) , the instruction typedef clObject<prType> cpObject would define a class cpObject that is not instantiated yet, but its parameters are defined, considering only the sight of the function. |
ag... |
Means the element is an argument of the method or the function. |
pr... |
Means the element is a parameter of the template. |
lc... |
Means the element is local to the method, the function or the instruction block. |
go... |
Means the element is global to the module. |
at... |
Means the element is an attribute of the class. |
td... |
Means the element is an alias for the parameters of a template. The syntax corresponds to the definition of the template. For instance, instead of writing template <class prArcData,class prNodeData> class clGraph , we can use an alias and write template <tdGraph> class clGraph . |
tu... |
Means the element is an alias for the parameters of a template. The syntax corresponds to the use of the template. For instance, instead of writing clGraph<prArcData,prNodeData> , we can use an alias and write clGraph<tuGraph> . |
ja... |
Means the element represents a Java class. |
jy... |
Means the element is a class or a type defined by the Java Native Interface (JNI). |
|