How to build a mex return structure?

I am unable to figure out how to build and attach matrices to the structure I have being returned
mwSize dims[2] = {1,NumChans};
plhs[0] = mxCreateStructArray(2, dims, NUMBER_OF_FIELDS, field_names);
I want to place matrices in one of the fields where I'll have a different one for each structure element. I can't seem to find any examples how best to do this, would there possibly be such an example?
Thanks

 Accepted Answer

Adam
Adam on 29 Jun 2016
Edited: Adam on 29 Jun 2016
You can create an mxArray as you would anywhere else, e.g.
mxArray* myArray = mxCreateDoubleMatrix( 3, 4, mxREAL );
double* dataPtr = mxGetPr( myArray );
// Some code here to fill up myArray however you want using dataPtr
mxSetField( plhs[0], 0, field_names{1}, myArray ); // Assign matrix to first field name of 1st structure in array
mxSetField( plhs[1], 1, field_names{1}, myOtherArray ); // Assign matrix to first field name of 2nd structure in array
etc
with myOtherArray created by whatever method you choose also.

8 Comments

a little more background, I'm using a C++ SDK to read a proprietary data file format, where my mex first extracts the number of channels, then loops through them. The channel read section has a single line function which gets the data for the current channel in the loop, where I'm creating and flushing the buffer used for this each loop, since I don't know how many datapoints there are until the channel information is read.
Here's an abbreviated version of the loop
// read the number of channels
if (ts.getChannelCount(&NumChans))
{
mwSize dims[2] = {1,1};
dims[1] = NumChans;
plhs[0] = mxCreateStructArray(2, dims, NUMBER_OF_FIELDS, field_names);
mxArray *tmp;
for (ChanIndex=0; ChanIndex<NumChans; ChanIndex++)
{
// Get number of data points, x-axis start time and sample rate for this channel
if ( ts.getPointCount(ChanIndex,&NumPoints) && ts.getXBase(ChanIndex, &XBase) && ts.getSampleRate(ChanIndex, &SampleRate) )
{
name_field = mxGetFieldNumber(plhs[0],"NumPoints");
tmp = mxCreateNumericMatrix((mwSize) 1,(mwSize) 1,mxUINT64_CLASS, mxREAL);
*mxGetPr(tmp) = (int long long) NumPoints;
mxSetFieldByNumber(plhs[0],ChanIndex,name_field,tmp);
}
// Read the data for this channel
FTFloat *DataBuf = new FTFloat[NumPoints];
if (ts.getData(ChanIndex, 0, (FTUnsLong)NumPoints, DataBuf))
{
this is where I want to asign the data read into DataBuff
into the plhs[0] structure in the "Data" field
name_field = mxGetFieldNumber(plhs[0],"Data");
mxSetFieldByNumber(plhs[0],ChanIndex,name_field,????);
delete[] DataBuf;
DataBuf = 0;
}
}
}
Adam
Adam on 29 Jun 2016
Edited: Adam on 29 Jun 2016
Well, you should just be able to create another mxArray and then copy your data directly from DataBuf into it as e.g.
mxArray myMatrix = mxCreateNumericArray( 1, NumPoints, mxSINGLE_CLASS, mxREAL );
float *dataPtr = static_cast<float *>( mxGetData( myMatrix ) );
memcpy( dataPtr, DataBuff, 4 * NumPoints );
or something vaguely similar. That code is just modified off the top of my head from code I use somewhere so it may need alterations with casting or other changes.
My problem is understanding how to configure the mx variables. I get a new vector of data each time through the loop, what I can't seem to do is get a variable built that will handle the variable number of channels and points of each channel that aren't known until run time.
It seems I need an array of mxArray pointers so I can fill unique mxArrays for each loop iteration. something like
mxArray *Data = new mxArray[numChans]
but this creates a mex error
Does this make sense?
mxArray *tmp, *Data[1000];
double *dataPtr;
then in the loop
Data[ChanIndex] = mxCreateDoubleMatrix( NumPoints, 1, mxREAL );
dataPtr = mxGetPr( Data[ChanIndex] );
/* Copy data into the mxArray */
for ( index = 0; index < NumPoints; index++ ) {
dataPtr[index] = DataBuf[index];
}
name_field = mxGetFieldNumber(plhs[0],"Data");
mxSetFieldByNumber(plhs[0],ChanIndex,name_field,Data[ChanIndex]);
The Data pointer array is hard coded to be large, is there a better way to do this?
@Jeff: This does not do what you think it does:
tmp = mxCreateNumericMatrix((mwSize) 1,(mwSize) 1,mxUINT64_CLASS, mxREAL);
*mxGetPr(tmp) = (int long long) NumPoints;
You created an mxArray of uint64 class with the first line. Then you try to copy a long long value into that array with the second line. But mxGetPr returns a (double *) type. So the second line converts NumPoints into a double and copies it into the memory location of a uint64. Then when you read this memory location as a uint64 you will get garbage. What you need to do is something like this instead:
long long *longlongptr;
:
tmp = mxCreateNumericMatrix((mwSize) 1,(mwSize) 1,mxUINT64_CLASS, mxREAL);
longlongptr = (long long *) mxGetData(tmp);
*longlongptr = (int long long) NumPoints;
This syntax works, but "new" doesn't seem to work to dynamically allocate mxArray pointers. Is there a way to do it?
James Tursa
James Tursa on 29 Jun 2016
Edited: James Tursa on 29 Jun 2016
Can you post your current code or pseudo-code with comments as to what you want at the end of the process? I.e., "I want an X-element structure with fields named AAA, BBB, etc and each field will contain ETC ETC".
I am not really sure where you are getting stuck. Once you know how many elements you want (NumChans?), you loop through them to set the field values. Looks like you are doing that already, so I don't see where you are having problems with this.
I neglected to make it an array of pointers, this works fine
mxArray **Data = new mxArray*[ NumChans ];

Sign in to comment.

More Answers (0)

Categories

Find more on MATLAB Compiler SDK in Help Center and File Exchange

Tags

Asked:

on 29 Jun 2016

Commented:

on 22 Jul 2016

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!