RTI Connext C API
Version 5.3.0
|
A sample of any complex data type, which can be inspected and manipulated reflectively. More...
A sample of any complex data type, which can be inspected and manipulated reflectively.
Objects of type DDS_DynamicData represent corresponding objects of the type identified by their DDS_TypeCode. Because the definition of these types may not have existed at compile time on the system on which the application is running, you will interact with the data using an API of reflective getters and setters.
For example, if you had access to your data types at compile time, you could do this:
Instead, you will do something like this:
DDS_DynamicData objects can represent any complex data type, including those of type kinds DDS_TK_ARRAY, DDS_TK_SEQUENCE, DDS_TK_STRUCT, DDS_TK_UNION, and DDS_TK_VALUE. They cannot represent objects of basic types (e.g. integers and strings). Since those type definitions always exist on every system, you can examine their objects directly.
The members of a data type can be identified in one of two ways: by their name or by their numeric ID. The former is often more transparent to human users; the latter is typically faster.
You define the name and ID of a type member when you add that member to that type. If you define your type in IDL or XML, the name will be the field name that appears in the type definition; the ID will be the one-based index of the field in declaration order. For example, in the following IDL structure, the ID of theLong
is 2.
For unions (DDS_TK_UNION), the ID of a member is the discriminator value corresponding to that member. To access the current discriminator of a union, you must use the DDS_DynamicData_get_member_info_by_index operation on the DynamicData object using an index value of 0. This operation fills in a DDS_DynamicDataMemberInfo, then you can access the populated DDS_DynamicDataMemberInfo::member_id field to get the current discriminator. Once you know the value of the discriminator, you can use it in the proper get/set_xxx() operations to access and set the member's value. Here is an example of accessing the discriminator:
The "members" of array and sequence types, unlike those of structure and union types, don't have names or explicit member IDs. However, they may nevertheless be accessed by "ID": the ID is one more than the index. (The first element has ID 1, the second 2, etc.)
Multi-dimensional arrays are effectively flattened by this pattern. For example, for an array theArray
[4][5], accessing ID 7 is equivalent to index 6, or the second element of the second group of 5.
To determine the length of a collection-typed member of a structure or union, you have two choices:
The Dynamic Data API is large when measured by the number of methods it contains. But each method falls into one of a very small number of categories. You will find it easier to navigate this documentation if you understand these categories.
Managing the lifecycle of DDS_DynamicData objects is simple. You have two choices:
You can also copy DDS_DynamicData objects:
You can test them for equality:
And you can print their contents:
Most methods get or set the value of some field. These methods are named according to the type of the field they access.
The names of types vary across languages. The programming API for each language reflects that programming language. However, if your chosen language does not use the same names as the language that you used to define your types (e.g., IDL), or if you need to interoperate among programming languages, you will need to understand these differences. They are explained the following table.
Type | IDL | C, C++ | C++/CLI (C#) | Java | Ada |
---|---|---|---|---|---|
16-bit integer | short | DDS_Short | System::Int16 | short | Standard.DDS.Short |
32-bit integer | long | DDS_Long | System::Int32 | int | Standard.DDS.Long |
64-bit integer | long long | DDS_LongLong | System::Int64 | long | Standard.DDS.Long_Long |
Unsigned 16-bit integer | unsigned short | DDS_UnsignedShort | System::UInt16 | short | Standard.DDS.Unsigned_Short |
Unsigned 32-bit integer | unsigned long | DDS_UnsignedLong | System::UInt32 | int | Standard.DDS.Long |
Unsigned 64-bit integer | unsigned long long | DDS_UnsignedLongLong | System::UInt64 | long | Standard.DDS.Unsigned_Long_Long |
float | float | DDS_Float | System::Single | float | Standard.DDS.Float |
double | double | DDS_Double | System::Double | double | Standard.DDS.Double |
long double | long double | DDS_LongDouble | DDS::LongDouble | double | Standard.DDS.Long_Double |
character | char | DDS_Char | System::Char | char | Standard.DDS.Char |
wide character | wchar | DDS_Wchar | System::Char | char | Standard.DDS.Wchar |
octet | octet | DDS_Octet | System::Byte | byte | Standard.DDS.Octet |
boolean | boolean | DDS_Boolean | System::Boolean | boolean | Standard.DDS.Boolean |
string | string | DDS_Char* | System::String | String | Standard.DDS.String |
wstring | wstring | DDS_Wchar* | System::String | String | Standard.DDS.Wide_String |
When working with a DDS_DynamicData object representing an array or sequence, calling one of the "get" methods below for an index that is out of bounds will result in DDS_RETCODE_NO_DATA. Calling "set" for an index that is past the end of a sequence will cause that sequence to automatically lengthen (filling with default contents).
When working with a DDS_DynamicData object whose type contains optional members, calling one of the "get" methods below on an unset optional member or any member that is part of an unset complex optional member will result in DDS_RETCODE_NO_DATA.
Get | Set |
---|---|
DDS_DynamicData_get_complex_member | DDS_DynamicData_set_complex_member |
In addition to getting or setting a field, you can "clear" its value; that is, set it to a default zero value.
Not all components of your application will have static knowledge of all of the fields of your type. Sometimes, you will want to query meta-data about the fields that appear in a given data sample.
Sometimes, you may want to change the association between a data object and its type. This is not something you can do with a typical object, but with DDS_DynamicData objects, it is a powerful capability. It allows you to, for example, examine nested structures without copying them by using a "bound" DDS_DynamicData object as a view into an enclosing DDS_DynamicData object.
Keys can be specified in dynamically defined types just as they can in types defined in generated code.
Due to the way in which DDS_DynamicData objects manage their internal state, it is typically more efficient, when setting the field values of a DDS_DynamicData for the first time, to do so in the declared order of those fields.
For example, suppose a type definition like the following:
The richness of the type system makes it difficult to fully characterize the performance differences between all access patterns. Nevertheless, the following are generally true:
my_float
, then my_bytes
, and finally my_short
.