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:
theValue = theObject.theField;
Instead, you will do something like this:
theValue = get(theObject, "theField");
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, DDS_TK_VALUE, and DDS_TK_SPARSE. 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.
You define the name and ID of a type member when you add that member to that type. When you define a sparse type, you will typically choose both explicitly. 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.
struct MyType { short theShort; long theLong; };
IDs work the same way for DDS_DynamicData objects representing arrays and sequences, since the elements of these collections have no explicit IDs: the ID is one more than the index. (The first element is ID 1, the second is 2, etc.) Array and sequence elements do not have names.
Multi-dimensional arrays are effectively flattened by the DDS_DynamicData API. 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.
For unions (DDS_TK_UNION), the ID of a member is the discriminator value corresponding to that member.
You can also copy DDS_DynamicData objects:
You can test them for equality:
And you can print their contents:
The names of integer 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# | Java |
---|---|---|---|---|
16-bit integer | short | DDS_Short | short | short |
32-bit integer | long | DDS_Long | int | int |
64-bit integer | long long | DDS_LongLong | long | long |
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).
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.
For example, suppose a type definition like the following:
struct MyType { float my_float; sequence<octet> my_bytes; short my_short; };
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
.