Skip to content

Latest commit

 

History

History
596 lines (469 loc) · 23.4 KB

dataTypes.rst

File metadata and controls

596 lines (469 loc) · 23.4 KB

Defining a data type via IDL

This section describes the data types that can be defined using IDL files, as well as other mechanisms for building data types using IDL files.

Supported IDL types

Be aware that Fast DDS-Gen is not case sensitive as it is specified in the IDL specification. To activate case sensitivity use option -cs when running Fast DDS-Gen (see :ref:`fastddsgen_supported_options`).

Primitive types

The following table shows the basic IDL types supported by Fast DDS-Gen and how they are mapped to C++11.

IDL C++11
char char
octet uint8_t
short int16_t
unsigned short uint16_t
long int32_t
unsigned long uint32_t
long long int64_t
unsigned long long uint64_t
float float
double double
long double long double
boolean bool
string std::string

Arrays

Fast DDS-Gen supports unidimensional and multidimensional arrays. Arrays are always mapped to std::array containers. The following table shows the array types supported and their mapping.

IDL C++11
char a[5] std::array<char,5> a
octet a[5] std::array<uint8_t,5> a
short a[5] std::array<int16_t,5> a
unsigned short a[5] std::array<uint16_t,5> a
long a[5] std::array<int32_t,5> a
unsigned long a[5] std::array<uint32_t,5> a
long long a[5] std::array<int64_t,5> a
unsigned long long a[5] std::array<uint64_t,5> a
float a[5] std::array<float,5> a
double a[5] std::array<double,5> a

Sequences

Fast DDS-Gen supports sequences, which map into the std::vector container. The following table represents how the map between IDL and C++11 is handled.

IDL C++11
sequence<char> std::vector<char>
sequence<octet> std::vector<uint8_t>
sequence<short> std::vector<int16_t>
sequence<unsigned short> std::vector<uint16_t>
sequence<long> std::vector<int32_t>
sequence<unsigned long> std::vector<uint32_t>
sequence<long long> std::vector<int64_t>
sequence<unsigned long long> std::vector<uint64_t>
sequence<float> std::vector<float>
sequence<double> std::vector<double>

Maps

Fast DDS-Gen supports maps, which are equivalent to the std::map container. The equivalence between types is handled in the same way as for sequences.

IDL C++11
map<char, unsigned long long> std::map<char, uint64_T>

Note

Only :ref:`idl_primitive_types` are currently supported.

Structures

You can define an IDL structure with a set of members with multiple types. It will be converted into a C++ class in which the members of the structure defined via IDL are mapped to private data members of the class. Furthermore, :func:`set` and :func:`get` member functions are created to access these private data members.

The following IDL structure:

struct Structure
{
    octet octet_value;
    long long_value;
    string string_value;
};

Would be converted to:

.. literalinclude:: /../code/FastDDSGenCodeTester.cpp
   :language: c++
   :start-after: // STRUCTURES_DATA_TYPE
   :end-before: //!

Structures can inherit from other structures, extending their member set.

struct ParentStruct
{
    octet parent_member;
};

struct ChildStruct : ParentStruct
{
    long child_member;
};

In this case, the resulting C++ code will be:

.. literalinclude:: /../code/FastDDSGenCodeTester.cpp
   :language: c++
   :start-after: // STRUCTURE_INHERITANCE
   :end-before: //!

Optional members

A member of a structure can be optional. This is achieved by writing the @optional annotation before the member.

struct StructWithOptionalMember
{
    @optional octet octet_opt;
};

An optional member is converted into a template class eprosima::fastcdr::optional<T>, where T is the member's type.

.. literalinclude:: /../code/FastDDSGenCodeTester.cpp
   :language: c++
   :start-after: // STRUCTURE_WITH_OPTIONAL
   :end-before: //!

Before reading the value of the optional member, it should be checked the optional contains a value using has_value() function. Accessing a null optional throws a eprosima::fastcdr::exception::BadOptionalAccessException exception.

.. literalinclude:: /../code/FastDDSGenCodeTester.cpp
   :language: c++
   :start-after: // ACCESSING_OPTIONAL_VALUE
   :dedent: 4
   :end-before: //!

Extensibility

In order to support evolving types without breaking interoperability, the concept of type extensibility is supported by Fast DDS-Gen. There are three extensibility kinds: final, appendable and mutable.

  • FINAL extensibility indicates that the type is strictly defined. It is not possible to add members while maintaining type assignability.
  • APPENDABLE extensibility indicates that two types, where one contains all of the members of the other plus additional members appended to the end, may remain assignable.
  • MUTABLE extensibility indicates that two types may differ from one another in the additional, removal, and/or transposition of members while remaining assignable.
@extensibility(FINAL)
struct FinalStruct
{
    octet octet_opt;
};

@extensibility(APPENDABLE)
struct AppendableStruct
{
    octet octet_opt;
};

@extensibility(MUTABLE)
struct MutableStruct
{
    octet octet_opt;
};

Note

XCDRv1 encoding algorithm is not able to manage correctly the deserialization of an appendable structure when it is used as a member of another one.

Unions

In IDL, a union is defined as a sequence of members with their own types and a discriminant that specifies which member is in use. An IDL union type is mapped as a C++ class with member functions to access the union members and the discriminant.

The following IDL union:

union Union switch(long)
{
   case 1:
    octet octet_value;
  case 2:
    long long_value;
  case 3:
    string string_value;
};

Would be converted to:

.. literalinclude:: /../code/FastDDSGenCodeTester.cpp
   :language: c++
   :start-after: // UNION_DATA_TYPE
   :end-before: //!

Bitsets

Bitsets are a special kind of structure, which encloses a set of bits. A bitset can represent up to 64 bits. Each member is defined as bitfield and eases the access to a part of the bitset.

For example:

bitset MyBitset
{
    bitfield<3> a;
    bitfield<10> b;
    bitfield<12, long> c;
};

The type :class:`MyBitset` will store a total of 25 bits (3 + 10 + 12) and will require 32 bits in memory (lowest primitive type to store the bitset's size).

  • The bitfield 'a' allows us to access to the first 3 bits (0..2).
  • The bitfield 'b' allows us to access to the next 10 bits (3..12).
  • The bitfield 'c' allows us to access to the next 12 bits (13..24).

The resulting C++ code will be similar to:

.. literalinclude:: /../code/FastDDSGenCodeTester.cpp
   :language: c++
   :start-after: // BITSET_DATA_TYPE
   :end-before: //!

Internally, it is stored as a std::bitset. For each bitfield, :func:`get` and :func:`set` member functions are generated with the smaller possible primitive unsigned type to access it. In the case of bitfield 'c', the user has established that this accessing type will be long, so the generated code uses int32_t instead of automatically use uint16_t.

Bitsets can inherit from other bitsets, extending their member set.

bitset ParentBitset
{
    bitfield<3> parent_member;
};

bitset ChildBitset : ParentBitset
{
    bitfield<10> child_member;
};

In this case, the resulting C++ code will be:

.. literalinclude:: /../code/FastDDSGenCodeTester.cpp
   :language: c++
   :start-after: // BITSET_INHERITANCE
   :end-before: //!

Note that in this case, :class:`ChildBitset` will have two std::bitset data members, one belonging to :class:`ParentBitset` and the other belonging to :class:`ChildBitset`.

Enumerations

An enumeration in IDL format is a collection of identifiers that have an associated numeric value. An IDL enumeration type is mapped directly to the corresponding C++11 enumeration definition.

The following IDL enumeration:

enum Enumeration
{
    RED,
    GREEN,
    BLUE
};

Would be converted to:

.. literalinclude:: /../code/FastDDSGenCodeTester.cpp
   :language: c++
   :start-after: // ENUMERATION_DATA_TYPE
   :end-before: //!

Bitmasks

Bitmasks are a special kind of Enumeration to manage masks of bits. It allows defining bit masks based on their position.

The following IDL bitmask:

@bit_bound(8)
bitmask MyBitMask
{
    @position(0) flag0,
    @position(1) flag1,
    @position(4) flag4,
    @position(6) flag6,
    flag7
};

Would be converted to:

.. literalinclude:: /../code/FastDDSGenCodeTester.cpp
   :language: c++
   :start-after: // BITMASK_DATA_TYPE
   :end-before: //!

The annotation bit_bound defines the width of the associated enumeration. It must be a positive number between 1 and 64. If omitted, it will be 32 bits. For each flag, the user can use the annotation position to define the position of the flag. If omitted, it will be auto incremented from the last defined flag, starting at 0.

Modules

In order to avoid collision between variable names, modules can be defined within the IDL file. A module would be converted into a namespace in C++.

Data types with a key

In order to use keyed topics, the user should define some key members inside the structure. This is achieved by writing the @key annotation before the members of the structure that are used as keys. For example in the following IDL file the id and type field would be the keys:

struct MyType
{
    @key long id;
    @key string type;
    long positionX;
    long positionY;
};

Fast DDS-Gen automatically detects these tags and correctly generates the serialization methods for the key generation function in TopicDataType (:func:`getKey`). This function will obtain the 128-bit MD5 digest of the big-endian serialization of the Key Members.

Including other IDL files

Other IDL files can be included in addition to the current IDL file. Fast DDS-Gen uses a C/C++ preprocessor for this purpose, and #include directive can be used to include an IDL file. Preprocessor directives guarding against multiple inclusion of the same IDL file are also advisable.

.. literalinclude:: /../code/FastDDSGenCodeTester.cpp
   :language: c++
   :start-after: // INCLUDE_MORE_IDL_FILES
   :end-before: //!

If Fast DDS-Gen does not find a C/C++ preprocessor in default system paths, the preprocessor path can be specified using parameter -ppPath. The parameter -ppDisable can be used to disable the usage of the C/C++ preprocessor.

Annotations

The application allows the user to define and use their own annotations as defined in the OMG IDL 4.2 specification. User annotations will be passed to TypeObject generated code if the -typeobject argument was used.

@annotation MyAnnotation
{
    long value;
    string name;
};

Additionally, the following standard annotations are builtin (recognized and passed to TypeObject when unimplemented).

Annotation Implemented behavior
@id [Unimplemented] Assign a 32-bit integer identifier to an element.
@autoid [Unimplemented] Automatically allocate identifiers to the elements.
@optional Setting an element as optional. More info in Optional Members.
@extensibility Applied to any element which is constructed. Allow specifying how the |br| element is allowed to evolve. More info in Extensibility.
@final Shortcut for @extensibility(FINAL)
@appendable Shortcut for @extensibility(APPENDABLE)
@mutable Shortcut for @extensibility(MUTABLE)
@position Setting a position to an element or group of elements. Used by bitmasks.
@value [Unimplemented] Allow setting a constant value to any element.
@key Alias for eProsima's @Key annotation. Indicate that a data member is part of the key |br| (please refer to :ref:`dds_layer_topic_instances` for more information).
@must_understand [Unimplemented] Indicate that the data member must be understood by any application |br| making use of that piece of data.
@default_literal [Unimplemented] Allow selecting one member as the default within a collection.
@default Allow specifying the default value of the annotated element.
@range [Unimplemented] Allow specifying a range of allowed values for the annotated element.
@min [Unimplemented] Allow specifying a minimum value for the annotated element.
@max [Unimplemented] Allow specifying a maximum value for the annotated element.
@unit [Unimplemented] Allow specifying a unit of measurement for the annotated element.
@bit_bound Allow setting a size to a bitmasks.
@external [Unimplemented] Force the annotated element to be placed in a dedicated data space.
@nested [Unimplemented] Allow indicating that the objects from the type under annotation will |br| always be nested within another one.
@verbatim [Unimplemented] Allow injecting some user-provided information into what the compiler |br| will generate.
@service [Unimplemented] Allow indicating that an interface is to be treated as a service.
@oneway [Unimplemented] Allow indicating that an operation is one way only, meaning that |br| related information flow will go from client to server but not back.
@ami [Unimplemented] Allow indicating that an interface or an operation is to be made |br| callable asynchronously.
@non_serialized The annotated member will be omitted from serialization.

Most unimplemented annotations are related to Extended Types.

Forward declaration

Fast DDS-Gen supports forward declarations. This allows declaring inter-dependant structures, unions, etc.

struct ForwardStruct;

union ForwardUnion;

struct ForwardStruct
{
    ForwardUnion fw_union;
};

union ForwardUnion switch (long)
{
    case 0:
        ForwardStruct fw_struct;
    default:
        string empty;
};

IDL 4.2 aliases

IDL 4.2 allows using the following names for primitive types:

int8
uint8
int16
uint16
int32
uint32
int64
uint64

IDL 4.2 comments

There are two ways to write IDL comments:

  • The characters /* start a comment, which terminates with the characters */.
  • The characters // start a comment, which terminates at the end of the line on which they occur.

Please refer to the IDL 4.2 specification (Section 7.2 Lexical Conventions) for more information on IDL conventions.

/* MyStruct definition */
struct MyStruc
{
    string mymessage;   // mymessage data member.
};