Multi-dimensional sequences

6 posts / 0 new
Last post
Offline
Last seen: 8 years 1 week ago
Joined: 07/27/2014
Posts: 5
Multi-dimensional sequences

Given the following IDL:

typedef sequence<int> z_type;

typedef sequence<z_type> y_type;

typedef sequence<y_type> x_type;

How does one initialise the size of each dimension to store the equivalent of a 3D array, eg [3][4][5].

How does one access cells within the sequence, i.e. x = fooSeq[1][1][1]?

Regards John

 

Organization:
Offline
Last seen: 3 years 1 week ago
Joined: 01/15/2013
Posts: 94

Hi John,

Any programming language of choice? I'll provide answers with the C API, as any other language will be just easier and more comfortable.

This page shows the reference API for generated sequences. The  FooSeq_ensure_length() method will set the sequence's length to your length of choice. It will resize the sequence if necessary to hold enough samples. Once you do that for the outer sequence, you can do the same for the inner sequences. To get a reference to the i-th member in the sequence you can use the  FooSeq_get_reference() method. Snippet of C code, showing the initialisation and then the access.

// It's important that you use the sequence initialiser, just for C
x_type outerSequence = DDS_SEQUENCE_INITIALIZER;
int i, j, k;
DDS_Boolean opResult = DDS_BOOLEAN_TRUE;
// You can also define these in the IDL file and constants will be created by RTI DDSGen
const DDS_Long SIZE_X = 3;
const DDS_Long SIZE_Y = 4;
const DDS_Long SIZE_Z = 5;
const DDS_Long INT_INIT = ...;

// Recall that in the C API the methods accept a *pointer* to the sequence
opResult = x_type_ensure_length(&outerSequence, SIZE_X, SIZE_X);
// Here we need to verify errors (or catch exceptions depending on the language)
// You could also spare the boolean variable and do if (!x_typeSeq_ensure_length(..)) {
if (!opResult) {
    // Handle errors
}
for (i = 0; i < SIZE_X; ++i) {
    y_type * middleSequence = NULL;
    middleSequence = x_type_get_reference(&outerSequence, i);
    *middleSequence = DDS_SEQUENCE_INITIALIZER;
    // Because we got a reference to the middle sequence, it's already a pointer
    opResult = y_type_ensure_length(middleSequence, SIZE_Y, SIZE_Y);
    if (!opResult) {
        // Handle errors
    }
    // Repeat operation for the inner-most sequence type
    for (j = 0; j < SIZE_Y; ++j) {
        z_type * innermostSequence = NULL;
        innermostSequence = y_type_get_reference(middleSequence, j);
        *innermostSequence = DDS_SEQUENCE_INITIALIZER;
        opResult = z_type_ensure_length(innermostSequence, SIZE_Z, SIZE_Z);
        if (!opResult) {
            // Handle errors
        }
        // Now you could loop to give the integer values initial values
        for (k = 0; k < SIZE_Z; ++k) {
            *z_type_get_reference(innermostSequence, k) = INT_INIT;
        }
    }
}

...
// Now to access elements in the sequences, e.g. [1][1][1] (recall that sequences are 0-indexed)
DDS_Long * intPointer = z_type_get_reference(y_type_get_reference(x_type_get_reference(&outerSequence, 0), 0), 0)
Offline
Last seen: 8 years 1 week ago
Joined: 07/27/2014
Posts: 5

 Thanks for the response Juan.

I forgot to mention I'm wrting C++ code and using the ndds_cpp.h file.

Prior to receiving your response I modified my IDL code to introduce intermediate structures as illustrated below. However from your response I guess I just start with the outermost sequence and allocate storage as we travel to the innermost sequence.

I'm also curious about the need for DDS_SEQUENCE_INITIALIZER. Can I assume it is not required for C++?

// Modified IDL
  
struct y_type
{
   sequence<int> z_data;
};

struct x_type
{
   sequence<y_type> y_data;
};

struct Foo
{
   sequence<x_type> x_data;
}            


// C++ code
Foo foo;

// Allocate storage for sequences
const int size=10;   
foo.x_data.ensure_length(size, size);
for (int i=0; i<size; i++)
{
  foo.x_data[i].y_data.ensure_length(size,size);
  for (int j=0; j < size; j++)
  {
     foo.x_data[i].y_data[j].ensure_length(size,size);
  }
}

// Now populate sequences
foo.x_data[1].y_data[2].z_data[3] = 1;                 
Offline
Last seen: 3 years 1 week ago
Joined: 01/15/2013
Posts: 94

Hi John,

Yes, you don't need the DDS_SEQUENCE_INITIALIZER constant for the C++ language (or any other than C). The pattern you mention is the correct one, allocate sequence memory from the outermost sequence to the innermost one.

Thanks,

Juanlu

Offline
Last seen: 2 years 6 months ago
Joined: 10/18/2013
Posts: 42

may be related.  i want to define a 2 dimensional dynamic sequence in my IDL, of type <string[1024], EnumerationType>


i can get through the rtiddsgen but i get compile errors in the generated code.  i'm using .NET

gianpiero's picture
Offline
Last seen: 2 months 1 week ago
Joined: 06/02/2010
Posts: 177

Jay,

could you post the idl and the errors you get so we can try to reproduce it?

Cheers,
  Gianpiero