RTI Connext C API  Version 5.1.0
DDS_DynamicData Struct Reference

A sample of any complex data type, which can be inspected and manipulated reflectively. More...

Detailed Description

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:

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.

Member Names and IDs

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. 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;
};

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:

DynamicDataMemberInfo memberInfo = new DynamicDataMemberInfo();
myDynamicData.get_member_info_by_index(memberInfo, 0);
DynamicDataMemberId discriminatorValue = memberInfo.member_id;
DDS_Long myMemberValue = myDynamicData.get_long(NULL, discriminatorValue);

Arrays and Sequences

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:

  1. Get the length along with the data: call the appropriate array accessor (see Getters and Setters) and check the resulting length.
  2. Get the length without getting the data itself: call DDS_DynamicData_get_member_info and check the resulting DDS_DynamicDataMemberInfo::element_count.

Available Functionality

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.

Lifecycle and Utility Methods

Managing the lifecycle of DDS_DynamicData objects is simple. You have two choices:

  1. Usually, you will go through a DDS_DynamicDataTypeSupport factory object, which will ensure that the type and property information for the new DDS_DynamicData object corresponds to a registered type in your system.
  2. In certain advanced cases, such as when you're navigating a nested structure, you will want to have a DDS_DynamicData object that is not bound up front to any particular type, or you will want to initialize the object in a custom way. In that case, you can call the constructor directly.
Lifecycle
DDS_DynamicDataTypeSupport DDS_DynamicData
DDS_DynamicDataTypeSupport_create_data DDS_DynamicData_new
DDS_DynamicDataTypeSupport_initialize_data DDS_DynamicData_initialize
DDS_DynamicDataTypeSupport_finalize_data DDS_DynamicData_finalize
DDS_DynamicDataTypeSupport_delete_data DDS_DynamicData_delete


You can also copy DDS_DynamicData objects:

You can test them for equality:

And you can print their contents:

Getters and Setters

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 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.

Integer Type Names Across Languages
Type IDL C, C++ C# Java Ada
16-bit integer short DDS_Short short short integer (range: (2^15)..((2^15)-1))
32-bit integer long DDS_Long int int integer (range: (2^31)..((2^31)-1))
64-bit integer long long DDS_LongLong long long integer (range: (2^63)..((2^63)-1))

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.

Basic Types
GetSet
DDS_DynamicData_get_long DDS_DynamicData_set_long
DDS_DynamicData_get_ulong DDS_DynamicData_set_ulong
DDS_DynamicData_get_short DDS_DynamicData_set_short
DDS_DynamicData_get_ushort DDS_DynamicData_set_ushort
DDS_DynamicData_get_longlong DDS_DynamicData_set_longlong
DDS_DynamicData_get_ulonglong DDS_DynamicData_set_ulonglong
DDS_DynamicData_get_float DDS_DynamicData_set_float
DDS_DynamicData_get_double DDS_DynamicData_set_double
DDS_DynamicData_get_longdouble DDS_DynamicData_set_longdouble
DDS_DynamicData_get_boolean DDS_DynamicData_set_boolean
DDS_DynamicData_get_octet DDS_DynamicData_set_octet
DDS_DynamicData_get_char DDS_DynamicData_set_char
DDS_DynamicData_get_wchar DDS_DynamicData_set_wchar
DDS_DynamicData_get_string DDS_DynamicData_set_string
DDS_DynamicData_get_wstring DDS_DynamicData_set_wstring
Structures, Arrays, and Other Complex Types
GetSet
DDS_DynamicData_get_complex_member DDS_DynamicData_set_complex_member
Arrays of Basic Types
GetSet
DDS_DynamicData_get_long_array DDS_DynamicData_set_long_array
DDS_DynamicData_get_ulong_array DDS_DynamicData_set_ulong_array
DDS_DynamicData_get_short_array DDS_DynamicData_set_short_array
DDS_DynamicData_get_ushort_array DDS_DynamicData_set_ushort_array
DDS_DynamicData_get_longlong_array DDS_DynamicData_set_longlong_array
DDS_DynamicData_get_ulonglong_array DDS_DynamicData_set_ulonglong_array
DDS_DynamicData_get_float_array DDS_DynamicData_set_float_array
DDS_DynamicData_get_double_array DDS_DynamicData_set_double_array
DDS_DynamicData_get_longdouble_array DDS_DynamicData_set_longdouble_array
DDS_DynamicData_get_boolean_array DDS_DynamicData_set_boolean
DDS_DynamicData_get_octet_array DDS_DynamicData_set_octet_array
DDS_DynamicData_get_char_array DDS_DynamicData_set_char_array
DDS_DynamicData_get_wchar_array DDS_DynamicData_set_wchar_array
Sequences of Basic Types
GetSet
DDS_DynamicData_get_long_seq DDS_DynamicData_set_long_seq
DDS_DynamicData_get_ulong_seq DDS_DynamicData_set_ulong_seq
DDS_DynamicData_get_short_seq DDS_DynamicData_set_short_seq
DDS_DynamicData_get_ushort_seq DDS_DynamicData_set_ushort_seq
DDS_DynamicData_get_longlong_seq DDS_DynamicData_set_longlong_seq
DDS_DynamicData_get_ulonglong_seq DDS_DynamicData_set_ulonglong_seq
DDS_DynamicData_get_float_seq DDS_DynamicData_set_float_seq
DDS_DynamicData_get_double_seq DDS_DynamicData_set_double_seq
DDS_DynamicData_get_longdouble_seq DDS_DynamicData_set_longdouble_seq
DDS_DynamicData_get_boolean_seq DDS_DynamicData_set_boolean_seq
DDS_DynamicData_get_octet_seq DDS_DynamicData_set_octet_seq
DDS_DynamicData_get_char_seq DDS_DynamicData_set_char_seq
DDS_DynamicData_get_wchar_seq DDS_DynamicData_set_wchar_seq

In addition to getting or setting a field, you can "clear" its value; that is, set it to a default zero value.

Query and Iteration

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.

Type/Object Association

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

Keys can be specified in dynamically defined types just as they can in types defined in generated code. However, there are some minor restrictions when sparse value types are involved (see DDS_TK_SPARSE).

  • If a type has a member that is of a sparse value type, that member cannot be a key for the enclosing type.
  • Sparse value types themselves may have at most a single key field. That field may itself be of any type.

Performance

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:

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:

  • It will be most performant to set the value of my_float, then my_bytes, and finally my_short.
  • The order of modification has a greater impact for types of kind DDS_TK_STRUCT and DDS_TK_VALUE than it does for types of kind DDS_TK_SPARSE.
  • Modifications to variable-sized types (i.e. those containing strings, sequences, unions, or optional members) are more expensive than modifications to fixed-size types.
MT Safety:
UNSAFE. In general, using a single DDS_DynamicData object concurrently from multiple threads is unsafe.

RTI Connext C API Version 5.1.0 Copyright © Mon Feb 3 2014 Real-Time Innovations, Inc