How do I access an element in a sequence of complex types using dynamic data?

Note: This solution applies to RTI Connext 4.x. and above.

This solution explains how to access members of a complex type (e.g.: struct) contained in a sequence using DynamicData

If a type is defined as follows:

struct Nested {
    long x;
};
struct Hello {
    sequence<Nested, 3> mySeq;
};
 

The steps to access the long value "x" in each Nested struct contained in the sequance "mySeq" are the following:

1. Assuming that an instance of Hello is received (my_struct), you have to bind a DynamicData object to the inner sequence:

DDS_DynamicData *my_inner_sequence = NULL;
my_inner_sequence = DDS_DynamicData_new(NULL, (const DDS_DynamicDataProperty_t*) &DDS_DYNAMIC_DATA_PROPERTY_DEFAULT);
if (my_inner_sequence == NULL) {
    /* print and handle error */
}   
retCode = DDS_DynamicData_bind_complex_member(my_struct,my_inner_sequence, NULL, 1); 

Using this code snippet, first you define and initialize the DynamicData object used to bind the inner sequence. Then, you have to bind the local object and the inner sequence.

There are two ways to bind a complex member: by name or by id. You can think of the id as the position of the member in the struct.

  • by member name: the third argument of the method must be the member name and the fourth must be DDS_DYNAMIC_DATA_MEMBER_ID_UNSPECIFIED
  • by member id: you have to set the name as NULL and indicate the position in the fourth argument (Note that IDs start from 1!).

2. Get the length of the sequence to use it to iterate:

DDS_DynamicDataInfo my_sequence_info;
DDS_DynamicData_get_info(my_inner_sequence, &my_sequence_info);

The length is available in  my_sequence_info.member_count

3. Iterate over the sequence to get the nested members:

DDS_DynamicData *my_inner_element = NULL;
my_inner_element = DDS_DynamicData_new(NULL, (const DDS_DynamicDataProperty_t*) &DDS_DYNAMIC_DATA_PROPERTY_DEFAULT);
if (my_inner_element == NULL) {
    /* print hand handle error */
}   
for (i = 0; i < my_sequence_info.member_count; i++) 
{
    retCode = DDS_DynamicData_bind_complex_member(my_inner_sequence, my_inner_element, NULL, i+1);
    retCode = my_inner_element->get_long(x, NULL, 1);
    if (retCode != DDS_RETCODE_OK)
    { 
        printf("Error getting long\n");
    } 
    else
    {
        // No errors getting the value. Use x here.  
        printf("Element %d: %d \n",i ,x);
    } 
    retCode = DDS_DynamicData_unbind_complex_member(my_inner_sequence, my_inner_element);
}

To bind the complex members inside a sequence, it's mandatory to use the id/position (setting the name to NULL). The id must start at 1, not 0.

4. When you have finished iterating, you have to unbind the sequence (as you did inside the for loop).

retCode = DDS_DynamicData_unbind_complex_member(my_struct,my_inner_sequence); 
5. Remember to finalize and deallocate the DynamicData object that you allocated previously:
 
if (my_inner_element != NULL) {
    DDS_DynamicData_delete(my_inner_element);
}  
if (my_inner_sequence != NULL) {
    DDS_DynamicData_delete(my_inner_sequence);
}  
 
Programming Language: