10.10. Dynamic Types profiles
Fast DDS supports the implementation of Dynamic Language Binding by defining them through XML files. Thus the topic data types can be modified without the need to modify the source code of the DDS application.
10.10.1. XML Structure
The definition of data type profiles in the XML file is done with the types
tag.
Each types
element can contain one or more Type definitions.
Defining several types within a types
element or a single type for each types
element has the same
result.
Below, an example of a stand-alone types definition via XML is shown.
<types xmlns="http://www.eprosima.com">
<type>
<!-- Type definition -->
</type>
<type>
<!-- Type definition -->
<!-- Type definition -->
</type>
</types>
Note
For more information on the difference between stand-alone and rooted definitions please refer to section Rooted vs Standalone profiles definition.
10.10.2. Type definition
Below, the types supported by eProsima Fast DDS are presented. For further information about the supported Dynamic Language Binding, please, refer to Supported Types. For each type listed below, an example of how to build the type’s XML profile is provided.
10.10.2.1. Member types
Member types are defined as any type that can belong to a Struct or a
Union, or be aliased by a Alias.
These can be defined by the <member>
XML tag.
A member can be annotated as key
(equivalent of the IDL’s @key
) by setting the key
attribute to "true"
.
<member name="my_long" type="int32" key="true"/>
10.10.2.2. Primitive types
Primitive types are built-in types and they should be declared as members of an aggregated type
(Structure Types or Union Types).
Primitive types are declared by attribute type
and the possible values are listed in the table below.
Please, refer to Primitive Types for more information on primitive types.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
All of them are declared as follows:
<struct name="PrimitivesStruct">
<member name="my_bool" type="boolean"/>
<member name="my_octet" type="byte"/>
<member name="my_char" type="char8"/>
<member name="my_wchar" type="char16"/>
<member name="my_long" type="int32"/>
<member name="my_ulong" type="uint32"/>
<member name="my_int8" type="int8"/>
<member name="my_uint8" type="uint8"/>
<member name="my_short" type="int16"/>
<member name="my_ushort" type="uint16"/>
<member name="my_longlong" type="int64"/>
<member name="my_ulonglong" type="uint64"/>
<member name="my_float" type="float32"/>
<member name="my_double" type="float64"/>
<member name="my_longdouble" type="float128"/>
</struct>
struct PrimitivesStruct
{
boolean my_bool;
octet my_octet;
char my_char;
wchar my_wchar;
long my_long;
unsigned long my_ulong;
int8 my_int8;
uint8 my_uint8;
short my_short;
unsigned short my_ushort;
long long my_longlong;
unsigned long long my_ulonglong;
float my_float;
double my_double;
long double my_longdouble;
};
10.10.2.3. String Types
String types should be defined as members of an aggregated type (Structure Types or
Union Types).
String types are defined with attribute type
set to string
or wstring
.
An optional attribute stringMaxLength
might used to set a maximum length for the string collection.
Please, refer to String Types for more information on string types.
<struct name="StringsStruct">
<member name="my_string" type="string"/>
<member name="my_wstring" type="wstring"/>
<member name="my_bounded_string" type="string" stringMaxLength="41925"/>
<member name="my_bounded_wstring" type="wstring" stringMaxLength="20925"/>
</struct>
struct StringsStruct
{
string my_string;
wstring my_wstring;
string<41925> my_bounded_string;
wstring<20925> my_bounded_wstring;
};
10.10.2.4. Enumeration Types
Enumeration types are defined using the <enum>
tag.
Attribute name
and at least one <enumerator>
child element are mandatory.
Enumeration literals are defined using the <enumerator>
tag with mandatory attribute name
.
Optionally, unsigned integer attribute value
might be added to set a specific value for the enumeration literal.
Note
value
attribute is equivalent to @value
builtin annotation.
Please, refer to Enumeration Types for more information on enumeration types.
<enum name="MyEnum">
<enumerator name="A" value="0"/>
<enumerator name="B" value="1"/>
<enumerator name="C"/>
</enum>
<struct name="EnumStruct">
<member name="my_enum" type="nonBasic" nonBasicTypeName="MyEnum"/>
</struct>
enum MyEnum
{
A,
B,
C
};
struct EnumStruct
{
MyEnum my_enum;
};
10.10.2.5. Bitmask Types
Bitmask types are defined using the <bitmask>
tag.
Attribute name
and at least on <bit_value>
child element are mandatory.
Optionally, bit_bound
attribute might be set to specify the bitmask bound (by default 32 bits).
Bitflag elements are defined using the <bit_value>
tag with mandatory attribute name
.
Optionally, position
attribute might be defined to set the bitflag position within the bitmask.
Please, refer to Bitmask Types for more information on bitmask types.
<bitmask name="MyBitMask" bit_bound="8">
<bit_value name="flag0" position="0"/>
<bit_value name="flag1"/>
<bit_value name="flag2"/>
<bit_value name="flag5" position="5"/>
</bitmask>
<struct name="BitmaskStruct">
<member name="my_bitmask" type="nonBasic" nonBasicTypeName="MyBitMask"/>
</struct>
@bit_bound(8)
bitmask MyBitMask
{
@position(0) flag0,
flag1,
flag2,
@position(5) flag5
};
struct BitmaskStruct
{
MyBitMask my_bitmask;
};
10.10.2.6. Alias Types
Alias types are defined using the <typedef>
tag.
Attributes name
and type
are mandatory.
Depending on the aliased type, some other mandatory and/or optional attributes might be necessary or available.
Non-primitive types must define the type
attribute as nonBasic
and include the nonBasicTypeName
attribute with the name of the aliased type.
Please, refer to Alias Types for more information on alias types.
<typedef name="MyAliasedEnum" type="nonBasic" nonBasicTypeName="MyEnum"/>
<!-- XSD does not allow to set bounds to aliased strings -->
<typedef name="MyAliasedBoundedString" type="string"/>
<typedef name="MyRecursiveAlias" type="nonBasic" nonBasicTypeName="MyAliasedEnum"/>
<struct name="AliasStruct">
<member name="my_aliased_enum" type="nonBasic" nonBasicTypeName="MyAliasedEnum"/>
<member name="my_aliased_bounded_string" type="nonBasic" nonBasicTypeName="MyAliasedBoundedString"/>
<member name="my_recursive_alias" type="nonBasic" nonBasicTypeName="MyRecursiveAlias"/>
</struct>
typedef MyEnum MyAliasedEnum;
typedef string<100> MyAliasedBoundedString;
typedef MyAliasedEnum MyRecursiveAlias;
struct AliasStruct
{
MyAliasedEnum my_aliased_enum;
MyAliasedBoundedString my_aliased_bounded_string;
MyRecursiveAlias my_recursive_alias;
};
10.10.2.7. Sequence Types
Sequence types should be defined as members of an aggregated type (Structure Types or
Union Types).
Sequence types are defined with mandatory attributes type
set to the collection’s element type, and
sequenceMaxLength
used to set the maximum collection’s length.
Unbounded sequences should set sequenceMaxLength
attribute to -1
.
Please, refer to Sequence types for more information on sequence types.
<struct name="SequenceStruct">
<member name="bitmask_sequence" type="nonBasic" nonBasicTypeName="MyBitMask" sequenceMaxLength="-1"/>
<member name="short_sequence" sequenceMaxLength="5" type="int16"/>
</struct>
struct SequenceStruct
{
sequence<MyBitMask> bitmask_sequence;
sequence<short, 5> short_sequence;
};
10.10.2.8. Array Types
Array types should be defined as members of an aggregated type (Structure Types or
Union Types).
Array types are defined with mandatory attributes type
set to the collection’s element type, and
arrayDimensions
used to set the collection’s dimensions.
The format of arrayDimensions
attribute value is the size of each dimension separated by commas.
Please, refer to Array types for more information on array types.
<struct name="ArrayStruct">
<member name="long_array" type="int32" arrayDimensions="2,3,4"/>
</struct>
struct ArrayStruct
{
long long_array[2][3][4];
};
10.10.2.9. Map Types
Map types should be defined as members of an aggregated type (Structure Types or
Union Types).
Map types are defined with mandatory attributes type
set to the map’s value type, key_type
set to the
map’s key type, and mapMaxLength
used to set the maximum map’s number of key-value pairs.
Unbounded maps should set mapMaxLength
attribute to -1
.
Please, refer to Map Types for more information on map types.
<struct name="MapStruct">
<member name="string_alias_unbounded_map" type="nonBasic" nonBasicTypeName="MyAliasedBoundedString" key_type="string" mapMaxLength="-1"/>
<member name="short_long_map" type="int32" key_type="int16" mapMaxLength="2"/>
</struct>
struct MapStruct
{
map<string, MyAliasedBoundedString> string_alias_unbounded_map;
map<short, long, 2> short_long_map;
};
10.10.2.10. Structure Types
Structure types are defined using the <struct>
tag with mandatory attribute name
.
Structure inheritance may be configured setting optional attribute baseType
.
XML Structure Types require at least one member defined.
Note
IDL specification introduced in version 4.1 the possibility of void content structures. Empty structures are not supported in XML Types profiles yet.
Structure members are defined using the <member>
tag with mandatory attributes name
and type
.
Depending on the member type, some other mandatory and/or optional attributes might be necessary or available.
Non-primitive types must define the type
attribute as nonBasic
and include the nonBasicTypeName
attribute with the name of the member type.
Note
Currently, XML Types profiles does not support setting the member ID or marking a member as key.
Please, refer to Structure Types for more information on structure types.
<struct name="InnerStruct">
<!-- XML does not support setting Member ID -->
<member name="first" type="int32"/>
</struct>
<!-- TODO(XTypes: Fix inheritance loading from XML profile) Fast DDS#4626 -->
<!-- <struct name="ParentStruct">
<member name="first" type="float32"/>
<member name="second" type="int64"/>
</struct>
<struct name="ComplexStruct" baseType="ParentStruct">
<member name="complex_member" type="nonBasic" nonBasicTypeName="InnerStruct"/>
</struct> -->
struct InnerStruct
{
@id(0x10) long first;
};
struct ParentStruct
{
float first;
long long second;
};
struct ComplexStruct : ParentStruct
{
InnerStruct complex_member;
};
10.10.2.11. Union Types
Union types are defined using the <union>
tag with mandatory attribute name
.
A mandatory discriminator child must be defined using <discriminator>
tag.
Discriminator element requires <type>
as mandatory attribute.
Union types also require at least one case child defined using the <case>
tag.
Each case child requires at least one label child using the <caseDiscriminator>
tag.
value
attribute is mandatory and defines the label value.
Several labels might be defined using several <caseDiscriminator>
elements.
Each case child must have exclusively one union member defined.
Union members are defined using the <member>
tag with mandatory attributes name
and type
.
Depending on the member type, some other mandatory and/or optional attributes might be necessary or available.
Non-primitive types must define the type
attribute as nonBasic
and include the nonBasicTypeName
attribute with the name of the member type.
At least one union member must be defined for the union type to be consistent.
Note
Currently, XML Types profiles does not support setting the member ID or marking a member as key.
Please, refer to Union Types for more information on the union types.
<union name="InnerUnion">
<discriminator type="int16"/>
<case>
<caseDiscriminator value="0"/>
<member name="first" type="nonBasic" nonBasicTypeName="PrimitivesStruct"/>
</case>
<case>
<caseDiscriminator value="1"/>
<caseDiscriminator value="default"/>
<member name="second" type="int64"/>
</case>
</union>
<union name="ComplexUnion">
<discriminator type="int32"/>
<case>
<caseDiscriminator value="0"/>
<caseDiscriminator value="1"/>
<member name="third" type="int32"/>
</case>
<case>
<caseDiscriminator value="default"/>
<member name="fourth" type="nonBasic" nonBasicTypeName="InnerUnion"/>
</case>
</union>
union InnerUnion switch (short)
{
case 0:
@id(0x10) PrimitivesStruct first;
case 1:
default:
long long second;
};
union ComplexUnion switch (long)
{
case 0:
case 1:
long third;
default:
InnerUnion fourth;
};
10.10.2.12. Bitset Types
Bitset types are defined using the <bitset>
tag with mandatory attribute name
.
Bitset inheritance may be configured setting optional attribute baseType
.
At least one bitfield child must be defined using bitfield
tag.
Bitfield elements require mandatory attribute bit_bound
with the number of bits managed by the bitfield (maximum
64 bits).
Optionally, attributes name
and type
might be defined.
An anonymous bitfield (attribute name
not set) is not accessible and serves as padding between named bitfields.
The type
attribute can ease bitfield management explicitly setting an integer type that handles the bitfield.
Please, refer to Bitset Types for more information about the bitset types.
<bitset name="ParentBitset">
<bitfield name="a" bit_bound="3"/>
<bitfield name="b" bit_bound="1"/>
<bitfield bit_bound="4"/>
<bitfield name="c" bit_bound="10"/>
<bitfield name="d" bit_bound="12" type="int16"/>
</bitset>
<!-- TODO(XTypes: Fix inheritance loading from XML profile) Fast DDS#4626 -->
<!--<bitset name="ChildBitSet" baseType="ParentBitSet">
<bitfield name="e" bit_bound="1"/>
<bitfield name="f" bit_bound="20" type="uint32"/>
</bitset>
<struct name="BitsetStruct">
<member name="my_bitset" type="nonBasic" nonBasicTypeName="ChildBitSet"/>
</struct>-->
bitset ParentBitSet
{
bitfield<3> a;
bitfield<1> b;
bitfield<4>;
bitfield<10> c;
bitfield<12, short> d;
};
bitset ChildBitSet : ParentBitSet
{
bitfield<1> e;
bitfield<20, unsigned long> f;
};
struct BitsetStruct
{
ChildBitSet my_bitset;
};
10.10.3. Loading XML Types profile in Fast DDS application
Fast DDS application can use types defined in XML configuration files once those files have been loaded into the
DomainParticipantFactory
using load_XML_profiles_file()
.
Types might be retrieved using DomainParticipantFactory::get_dynamic_type_builder_from_xml_by_name()
.
After getting the DynamicType, objects of DynamicPubSubType
class might be instantiated and used to write/read
data.
// Create a DomainParticipant
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
if (nullptr == participant)
{
// Error
return;
}
// Load the XML File
if (RETCODE_OK ==
DomainParticipantFactory::get_instance()->load_XML_profiles_file("my_profiles.xml"))
{
// Retrieve instance of the desired type
DynamicTypeBuilder::_ref_type my_struct_type;
if (RETCODE_OK !=
DomainParticipantFactory::get_instance()->get_dynamic_type_builder_from_xml_by_name(
"MyStruct", my_struct_type))
{
// Error
return;
}
// Register MyStruct type
TypeSupport my_struct_type_support(new DynamicPubSubType(my_struct_type->build()));
my_struct_type_support.register_type(participant, nullptr);
}
else
{
std::cout << "Cannot open XML file \"types.xml\". "
<< "Please, set the correct path to the XML file"
<< std::endl;
}