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
采纳的回答
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 个评论
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;
}
}
}
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
2016-6-29
编辑:James Tursa
2016-6-29
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 ];
更多回答(0 个)
类别
在 帮助中心 和 File Exchange 中查找有关 Write C Functions Callable from MATLAB (MEX Files) 的更多信息
另请参阅
选择网站
选择网站以获取翻译的可用内容,以及查看当地活动和优惠。根据您的位置,我们建议您选择:。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
