3

I'm trying to use a dynamically growing array of structs in a piece of code that is supposed to be converted to C with Coder:

I initialize the struct and then declare its fields variable size for coder, then i proceed to grow the struct. Note that i have simplified this example to aid in readability of the generated code, so the reason for me using an array of structs is not obvious from this example.

MATLAB:

function [ events ] = testArraysOfStructs( data)
//%#codegen

ii=1;
events = struct('typ'   ,int32(0),...
                'title' ,int32(1),...
                'value' ,double(0),...
                'sta'   ,int32(2),...
                'end'   ,int32(3));

coder.varsize('events','events.typ','events.title','events.value','events.sta','events.end','events.title')

for n=1:length(data.temperatur_spikes_daily)

    events(ii).typ      = int32(101);
    events(ii).title    = int32(1234);
    events(ii).value    = double(1234);
    events(ii).sta      = int32(4321);
    events(ii).end      = int32(3412);

    ii = length(events)+1;
end
end

The problem is, in the generated code, the variable ii disappears and the data is continuously written onto the same array elements of the struct without any regard for the number of iterations of the loop that is supposed to grow it.

C:

void testArraysOfStructs(const struct0_T *data, struct1_T events_data[], int
  events_size[2])
{
  struct1_T r0;
  int n;
  r0.typ.size[0] = 1;
  r0.typ.size[1] = 1;
  r0.typ.data[0] = 0;
  r0.title.size[0] = 1;
  r0.title.size[1] = 1;
  r0.title.data[0] = 1;
  r0.value.size[0] = 1;
  r0.value.size[1] = 1;
  r0.value.data[0] = 0.0;
  r0.sta.size[0] = 1;
  r0.sta.size[1] = 1;
  r0.sta.data[0] = 2;
  r0.end.size[0] = 1;
  r0.end.size[1] = 1;
  r0.end.data[0] = 3;
  events_size[0] = 1;
  events_size[1] = 1;
  events_data[0] = r0;
  for (n = 0; n < data->temperatur_spikes_daily->size[0]; n++) {
    events_data[0].typ.size[0] = 1;
    events_data[0].typ.size[1] = 1;
    events_data[0].typ.data[0] = 101;
    events_data[0].title.size[0] = 1;
    events_data[0].title.size[1] = 1;
    events_data[0].title.data[0] = 1234;
    events_data[0].value.size[0] = 1;
    events_data[0].value.size[1] = 1;
    events_data[0].value.data[0] = 1234.0;
    events_data[0].sta.size[0] = 1;
    events_data[0].sta.size[1] = 1;
    events_data[0].sta.data[0] = 4321;
    events_data[0].end.size[0] = 1;
    events_data[0].end.size[1] = 1;
    events_data[0].end.data[0] = 3412;
  }
}

I suppose i have an error in declaring the struct dynamic, but unfortunately the documentation only contains examples for declaring either standard arrays dynamic or preallocating the size of the array of structs, even though dynamic sizing is mentioned as being supported. Any help in getting this to work would be appreciated.

sobek
  • 1,386
  • 10
  • 28

1 Answers1

3

Short answer: growing an array by indexing one beyond the end is not supported using Coder.

So your loop that increases the size of events on every iteration is not supported for Coder. You could use:

function [ events ] = foo(data)
%#codegen

events = struct('typ'   ,int32(0),...
                'title' ,int32(1),...
                'value' ,double(0),...
                'sta'   ,int32(2),...
                'end'   ,int32(3));

for n = 1:length(data.temperatur_spikes_daily)
    events = [events, struct('typ'   ,int32(101),...
                'title' ,int32(1234),...
                'value' ,double(1234),...
                'sta'   ,int32(4321),...
                'end'   ,int32(3412))];
end

or:

function [ events ] = foo(data)
%#codegen
% Allocate events
s = struct('typ'   ,int32(0),...
    'title' ,int32(1),...
    'value' ,double(0),...
    'sta'   ,int32(2),...
    'end'   ,int32(3));
events = coder.nullcopy(repmat(s, 1, length(data.temperatur_spikes_daily)));

% Populate values of events
for n = 1:numel(events)
    events(n).typ      = int32(101);
    events(n).title    = int32(1234);
    events(n).value    = double(1234);
    events(n).sta      = int32(4321);
    events(n).end      = int32(3412);
end

instead.

If you generate a MEX function from your original code rather than standalone code and run this MEX function in MATLAB you'll get an error:

Index exceeds matrix dimensions.  Index value 2 exceeds valid range [1-1] of array events.

Error in foo (line 15)
    events(ii).typ      = int32(101);

Generating and running a MEX function is the best way to verify that your MATLAB code is using constructs which are supported for Coder.

Ryan Livingston
  • 1,898
  • 12
  • 18
  • I guess i misread what they wrote about dynamic fields of arrays of structs. Your first suggestion looks like it might work for me. I'll accept the answer once i have tried it out. – sobek Sep 17 '14 at 17:25