GaudiObjDesc - frequently asked questions |
Home | Computing | Notes | Meetings | Subsystems | Search |
Note: All questions marked with are only related to the head-revision of the GaudiObjDesc-package. |
<IMPORT> |
How does an import work? | |
I want to force GOD not to include a special type, how can I do that? |
<CLASS> |
<CONSTRUCTOR> |
<LOCATION> |
How does the <location>-element work? | |
How can I concatenate locations? |
<NAMESPACE> |
How does the <namespace>-element work? |
<ENUM> |
How does the <enum>-element work? |
<TYPEDEF> |
How does the <typedef>-element work? |
<METHOD> |
How can I only specify a method-declaration (and no implementation) in the .h-file? | |
How can I produce pure virtual functions? |
<ATTRIBUTE> |
I want to suppress the casting of floats to doubles and vice versa during serialization, how? | |
How can I disable the serializing of an attribute? | |
How can I define arrays? |
<RELATION> |
How can I disable the serializing of an attribute? | |
Is there a difference between the values 'M', 'm', 'N' and 'n' for the multiplicity-attribute? |
<BITFIELD> |
What is a bitfield? | |
How does a bitfield work? |
There are two fragments in GaudiObjDesc which handle the execution of the tools for writing the C++-header-files and the dictionary information. Within these two fragments the location of the output is hardwired and they will go to the directories '/Event' and '/dict' and then write files to the local dir.
There are two fragments in GaudiObjDesc which handle the execution of the tools for writing the C++-header-files and the dictionary information. Within these two fragments the location of the output is hardwired and they will go to the directories '/Event' and '/dict' and then write files to the local dir.
Both tools accept optional flags which can be also set within the requirements-file. The flag for redirecting the output is '-o'. In the requirements-file of a package one may redirect now the output for the header- and dictionary-files for this package only.
E.g. to redirect the header-files for package Kernel/LHCbKernel to the directory 'Kernel'
macro
LHCbKernelObj2Doth_GODflags " -o ../Kernel/ " \ WIN32 " -o ..\Kernel\ " document obj2doth LHCbKernelObj2Doth ../xml/LHCbKernel.xml |
After redirecting the output of the header-files, the dictionary-tool must be made aware that the location of the header-files is no longer in the default-directory. This can be done with the option '-l directory'. E.g. for the previous example of LHCbKernel this will look like
macro
LHCbKernelObj2Dict_GODflags " -l Kernel/ " \ WIN32 " -l Kernel\ " document obj2dict LHCbKernelObj2Dict ../xml/LHCbKernel.xml |
The drawback for this current solution is, that the directories '/Event' and '/dict' will be still created although one maybe does not need them.
The new features of GaudiObjDesc v3r0 are:
A XML-editor was developed by Sebastien Ponce, this editor can be used for both the detector and event object descriptions. This editor is called 'XMLEditor' and can be checked out from the LHCb-cvs-repository. The current version is v4r2.
Other possible XML-Editors for Windows are XMLSpy or XMLWriter.
To overwrite the serializing functions you need to provide a self-defined method with the signature of the serializing method.
E.g. to overwrite the output-serializer one has to provide something like:
<method type="StreamBuffer&"
name="serialize" virtual="TRUE" const="TRUE" desc="special serializer for
writing"> <arg name="s" type="StreamBuffer" inout="BOTH" /> </method> |
for the input-serializer the signature will loke like:
<method type="StreamBuffer&"
name="serialize" virtual="TRUE" desc="special serializer for reading"> <arg name="s" type="StreamBuffer" inout="BOTH" /> </method> |
and for the ascii-output-serializer you have to provide a method like this.
<method type="std::ostream&"
name="fillStream" virtual="TRUE" const="TRUE" desc="special serializer to
ASCII stream"> <arg name="s" type="std::ostream" inout="BOTH" /> </method> |
For all these methods you have either the possiblity to provide the code inline or not. If you want to have an inline function the code has to be inside the <code>-subelement of these methods. If no <code>-subelement is provided, only the declaration of the method will be produced and the implementation has to be inside a separate cpp-file.
For every non fundamental type GaudiObjDesc will try to include the right class from the right place. For this reason it will look at another XML-file (GaudiCppExport.xml) where the information from many classes from the Gaudi-, LHCb- and CLHEP-packages are stored. If the information cannot be found there, this warning will be printed and the information about the class has to be imported separately. (see How does an import work?)
Never use an empty element without attributes (e.g. to specify empty code for a method). XERCES 1.5.2 which is the actual XML-parser for the Gaudi Object Description tools crashes if one uses such an element. To specify an empty element use e.g.
<code> </code> |
Sometimes it is necessary to explicitly include extra information to the header-file. In order to do this the correct header-file from the right package has to be included using the <import>-element. To import e.g. the file 'CaloDigit.h' from the package 'Calo' the import will look like:
<import name='Calo/CaloDigit'/> |
Note that there is no '.h' at the end of 'CaloDigit'.
ATTENTION: In order to include files from the new Event-model the package must be always 'Event' (e.g. <import name="Event/CaloDigit"/>
A statement like
<import name='TypeName' ignore='TRUE'/> |
will force GOD not to put 'TypeName' in the include-statements of your .h-file. This may be needed when you define a e.g. a typedef or enum in a different class or package and you want to use this type in another class.
Setting the <class>-attribute stdVectorTypeDef='TRUE' triggers the creation of
typedef std::vector<ClassName*> ClassNameVector; |
The 'id'-attribute of the <class>-element specifies the class-ID of this class. Specifying the 'id'-attribute triggers two actions:
There are two possibilities why this can happen:
<class name='Class1'
author='...' desc='...'> <base name='KeyedObject<int>'/> <!-- ... other elements of class1 ... --> </class> <class name='Class2' author='...' desc='...'> <base name='Class1'/> <!-- ... other elements of class2 ... --> </class> |
while the reverse order (Class2 before Class1) will not produce the typedef for the KeyedContainer for Class2.
If the base-class is not described in the same xml-file the tools will have no notion about its existence, so the creation of this template has to be forced with the <class>-attribute keyedContTypeDef='TRUE'
The <class>-element has an attribute 'location'. Setting this attribute to a value will produce a namespace outside the class like
namespace
L0CaloCandidateLocation { static const std::string& Default = "/some/string/location/"; } |
If there is more than one possibility where the class may appear in the transient data store, you can specify these additional locations with the <location>-element (see How does the <location>-element work?).
By setting the <class>-attribute stdVectorTypeDef = 'TRUE' GOD will produce a typedef like
typedef std::vector<MCParticle*> MCParticleVector; |
By setting the <class>-attribute serialize='FALSE'.
It was agreed that every class needs a standard constructor of this kind. This standard constructor initialises each <attribute> if possible. When doing this initialisation the following precedence will be taken into account:
Take care that this default initialisation will only be done for the default constructor with 0 arguments. If this constructor is overwritten there will be no default initialisation.
Overwriting of the default constructor with 0 arguments can be done with
<constructor desc='description
of constructor'> <code> ... C++-code ... </code> </constructor> |
The initialisation of values with the self-defined constructor can be done with the 'initList'-attribute. E.g.
<constructor initList='int1(12), int2(21)'/> |
The <location>-element should be used to specify additional possible locations of the class in the transient event store. If there is a default-location for the class, the 'location'-attribute of <class> should be used (see How can I define the default location of the class in the TDS?). The places specified with <location> will be appended to this namespace.
Example:
<class name='MyClass'
location='/Event/default/location/' ...> <location name='locationTwo' place='/Event/second/loc/'/> <location name='locationThree' place='/Event/third/loc/'/> ... </class> |
will produce a namespace outside the class which looks like
namespace MyClassLocation
{ static const std::string& Default = "/Event/default/location/"; static const std::string& locationTwo = "/Event/second/loc/"; static const std::string& locationThree = "/Event/third/loc/"; } |
It was proposed that one should be able to define parts of locations and concatenate them afterwards. By default GOD will take the 'place'-attribute and surrounded by quotes as the value of the static const string in the namespace. For concatenating variables this surrounding of the place-value with quotes can be disabled by setting the noQuote-attribute to 'TRUE', e.g.
<location name='base'
place='MC/'/> <location name='ext1' place='IT/Hits'/> <location name='location1' place='base + ext1' noQuote='TRUE'/> |
The <namespace>-element is a sub-element of <package>. For the time being it may contain <enum>- and <class>-elements in any order and number e.g.
<package name="Eventpackage"> <namespace name="EventNamespace" desc="Description of ..."> <enum .../> <!-- ... more classes or enums ... --> </namespace> </package> |
The <namespace>-element has two attributes 'name' and 'desc' which are also mandatory. In the example above from this namespace a file 'EventNamespace.h' with this content will be created.
The <enum>-element can either be a sub-element of <namespace> or <class>. It's attributes are:
Name | Values | Default |
name | mandatory | none |
desc | mandatory | none |
value | mandatory | none |
access | 'PRIVATE','PROTECTED','PUBLIC' | 'PRIVATE' |
If <enum> is a sub-element of <namespace> the 'access'-attribute will not be taken into account. The 'value'-attribute may take any string that should be inside the brackets of the enum.
Example:
<class name='class1'
desc='...'> <enum name='flags' value='fl1=1, fl2, fl3' desc='desc of flags'/> </class> |
The <typedef>-element can reside either in the PUBLIC, PROTECTED or PRIVATE area of a class. It's attributes are
Name | Values | Default |
type | mandatory | none |
def | mandatory | none |
desc | mandatory | none |
access | 'PRIVATE','PROTECTED','PUBLIC' | 'PRIVATE' |
The 'type'-attribute may take any string that is appropriate to define a c++-sequence. The def is the name that this typedef has.
Example
<class name='class1'
desc='...'> <typedef type='std::vector<int>' def='vecOfInt' desc='desc of typedef' access='PUBLIC'/> </class> |
This depends on the <code>-subelement. If this sub-element is provided GaudiObjDesc will produce an inline-implementation of the method. If no <code>-subelement is provided, only the declaration of the method will be produced inside the class and a manual implementation of the method inside a cpp-file is left to the user.
Pure virtual functions can be specified by setting the 'virtual'-attribute of <method> to 'PURE'. E.g.
<method type='int' name='type' virtual='PURE'/> |
will produce a method-declaration like
virtual int type() = 0; |
For the time being all attributes with type 'double' will be casted into type 'float' when serializing and vice versa when deserializing. If one wants the double-value of the attribute written to the tape the <attribute>-attribute noCast has to be set to 'TRUE', e.g.
<attribute type='double' name='helicity' noCast='TRUE' desc='Helicity'/> |
By setting the <attribute>-attribute serialize='FALSE' e.g.
<attribute type='int' name='id' serialize='FALSE' desc='id no'/> |
By setting 'array' of the <attribute>-element to a value an array of the specified type will be created. E.g.
<attribute type='int' name='cell' array='5' desc='desc of cell'/> |
will produce an array
int cell[5]; ///< desc of cell |
By setting the <relation>-attribute serialize='FALSE' e.g.
<relation type='MCParticle' name='redundantParticle' serialize='FALSE' desc='...'/> |
There is no difference between these values, they all specify a 1-N relation, but as the specifications in the DTD are case-sensitive and both 'm' and 'n' are usually used to specify this kind of relation all 4 values may be used equally.
A bitfield in GaudiObjDesc is an unsigned long integer which stores within its 4 bytes several bitfields representing different values. The ranges and names of these bitfields can be set with the <bitfield>-element which is always a sub-element of <attribute>.
If you want to create a bitfield you first have to create an attribute with the type='bitfield'. This allows you then to have several sub-elements <bitfield> which will specify the exact behaviour of the different bits of the bitfield.
The <bitfield>-element has the following attributes:
Name | Values | Default | Description |
name | mandatory | none | Name of the bitfield |
length | mandatory | none | Length either bits or other bitfields |
desc | mandatory | none | Description of bitfield |
startAtOne | 'TRUE','FALSE' | 'FALSE' | Range of number is '0 to n-1' or '1 to n' |
setMeth | 'TRUE','FALSE' | 'TRUE' | create setter |
getMeth | 'TRUE','FALSE' | 'TRUE' | create getter |
startBit | optional | none | starting bit of the field (not implemented yet!!!) |
Example:
<attribute type='bitfield'
name='channelID' desc='IT Channel ID'> <bitfield name='strip' length='16' desc='Strip'/> <bitfield name='wafer' length='8' desc='Wafer'/> <bitfield name='uniqueWafer' length='strip, wafer' desc='Unique wafer'/> </attribute> |
will produce
private: enum channelIDBits {stripBits = 0, waferBits = 16}; ///< Offsets of bitfield channelID enum channelIDMasks {stripMask = 0x0000ffff, waferMask = 0x00ff0000, uniqueWafer = stripMask + waferMask}; ///< Bitmasks for bitfield channelID unsigned long m_channelID; ///< IT Channel ID |
and the setters and getters for the attribute channelID and the three bitfields.
This page was last edited by SR on November 10, 2003. |