yu quan
yu quan

Reputation: 161

copy multi-dimension C array to Matlab mxArray type

I'm writing a c++ code that opens Matlab API engine. In the demo file Matlab_ROOT/extern/examples/eng_mat/engdemo.cpp, it shows how to copy a simple 1d c style array to a mxArray:

mxArray *T = NULL; double time[10] = {};
T = mxCreateDoubleMatrix( 1,10,mxREAL);
memcpy((void*)mxGetPr(T), (void*)time, sizeof(time));

I can understand this code; so a 1d mxArray object stores the elements linearly.

However, suppose I have a 2d (or more) c array and mxArray of same size:

double time[3][5]; 
mxArray *T; 
T = mxCreateDoubleMatrix(3,5,mxREAL);

and I want to copy the elements of the c array time into mxArray T. How can I do this? I suppose if I use memcpy, it would depend on the sequence of element storage in mxArray objects. Thanks!

Upvotes: 2

Views: 1738

Answers (2)

yu quan
yu quan

Reputation: 161

One way of doing this is illustrated in another Matlab demo file matlabroot/extern/examples/refbook/arrayFillSetData.c. Things works well except that the c style array has to be in a Matlab-supported type and in linear form. Matlab stores 2d array in column major and c in row major, so care must be taken. A transpose action might be needed.

#define ROWS 2
#define COLUMNS 2
#define ELEMENTS 4

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
UINT16_T *dynamicData;                        /* pointer to dynamic data */
const UINT16_T data[] = {2, 3, 2, 1};  /* existing data */
mwSize index;

/* Check for proper number of arguments. */
if ( nrhs != 0 ) {
    mexErrMsgIdAndTxt("MATLAB:arrayFillSetData:rhs",
            "This function takes no input arguments.");
} 

/* Create a local array and load data */
dynamicData = mxCalloc(ELEMENTS, sizeof(UINT16_T));
for ( index = 0; index < ELEMENTS; index++ ) {
    dynamicData[index] = data[index];
}

/* Create a 0-by-0 mxArray; you will allocate the memory dynamically */
plhs[0] = mxCreateNumericMatrix(0, 0, mxUINT16_CLASS, mxREAL);

/* Point mxArray to dynamicData */
mxSetData(plhs[0], dynamicData);
mxSetM(plhs[0], ROWS);
mxSetN(plhs[0], COLUMNS);

/* Do not call mxFree(dynamicData) because plhs[0] points to dynamicData */

return;
}

Upvotes: 2

Shai
Shai

Reputation: 114966

No matter what the dimensionality of your mxArray matlab always stores it as a continuous chunk in memory (column first order). That is, if your matrix M is 2-by-3

M = [ 11, 12, 13;
      21, 22, 23 ];

In memory, Matlab stores it as

[11, 21, 12, 22, 13, 23]

(The same order you'll get if you do M(:)).

Therefore, to convert a double[3][5] to mxArray you'll have to issue several memcpy commands:

double* ptr = mxGetPr( T );
for ( int i=0; i<3; i++ )
    memcpy( (void*)(ptr+i*5), (void*)time[i], 5*sizeof(double) );

Upvotes: 3

Related Questions