External Interfaces/API |
Passing Structures and Cell Arrays
Passing structures and cell arrays into MEX-files is just like passing any other data types, except the data itself is of type mxArray
. In practice, this means that mxGetField
(for structures) and mxGetCell
(for cell arrays) return pointers of type mxArray
. You can then treat the pointers like any other pointers of type mxArray
, but if you want to pass the data contained in the mxArray
to a C routine, you must use an API function such as mxGetData
to access it.
This example takes an m-by-n structure matrix as input and returns a new 1-by-1 structure that contains these fields:
int
, double
, and so on.
/* * ============================================================= * phonebook.c * Example for illustrating how to manipulate structure and cell * array * * Takes a (MxN) structure matrix and returns a new structure * (1x1) containing corresponding fields:for string input, it * will be (MxN) cell array; and for numeric (noncomplex, scalar) * input, it will be (MxN) vector of numbers with the same * classID as input, such as int, double etc.. * * This is a MEX-file for MATLAB. * Copyright (c) 1984-2000 The MathWorks, Inc. * ============================================================= */ /* $Revision: 1.9 $ */ #include "mex.h" #include "string.h" #define MAXCHARS 80 /* max length of string contained in each field */ /* The gateway routine. */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { const char **fnames; /* pointers to field names */ const int *dims; mxArray *tmp, *fout; char *pdata; int ifield, jstruct, *classIDflags; int NStructElems, nfields, ndim; /* Check proper input and output */ if (nrhs != 1) mexErrMsgTxt("One input required."); else if (nlhs > 1) mexErrMsgTxt("Too many output arguments."); else if (!mxIsStruct(prhs[0])) mexErrMsgTxt("Input must be a structure."); /* Get input arguments */ nfields = mxGetNumberOfFields(prhs[0]); NStructElems = mxGetNumberOfElements(prhs[0]); /* Allocate memory for storing classIDflags */ classIDflags = mxCalloc(nfields, sizeof(int)); /* Check empty field, proper data type, and data type consistency; get classID for each field. */ for (ifield = 0; ifield < nfields; ifield++) { for (jstruct = 0; jstruct < NStructElems; jstruct++) { tmp = mxGetFieldByNumber(prhs[0], jstruct, ifield); if (tmp == NULL) { mexPrintf("%s%d\t%s%d\n", "FIELD:", ifield+1, "STRUCT INDEX :", jstruct+1); mexErrMsgTxt("Above field is empty!"); } if (jstruct == 0) { if ((!mxIsChar(tmp) && !mxIsNumeric(tmp)) || mxIsSparse(tmp)) { mexPrintf("%s%d\t%s%d\n", "FIELD:", ifield+1, "STRUCT INDEX :", jstruct+1); mexErrMsgTxt("Above field must have either " "string or numeric non-sparse data."); } classIDflags[ifield] = mxGetClassID(tmp); } else { if (mxGetClassID(tmp) != classIDflags[ifield]) { mexPrintf("%s%d\t%s%d\n", "FIELD:", ifield+1, "STRUCT INDEX :", jstruct+1); mexErrMsgTxt("Inconsistent data type in above field!"); } else if (!mxIsChar(tmp) && ((mxIsComplex(tmp) || mxGetNumberOfElements(tmp) != 1))) { mexPrintf("%s%d\t%s%d\n", "FIELD:", ifield+1, "STRUCT INDEX :", jstruct+1); mexErrMsgTxt("Numeric data in above field " "must be scalar and noncomplex!"); } } } } /* Allocate memory for storing pointers */ fnames = mxCalloc(nfields, sizeof(*fnames)); /* Get field name pointers */ for (ifield = 0; ifield < nfields; ifield++) { fnames[ifield] = mxGetFieldNameByNumber(prhs[0],ifield); } /* Create a 1x1 struct matrix for output */ plhs[0] = mxCreateStructMatrix(1, 1, nfields, fnames); mxFree(fnames); ndim = mxGetNumberOfDimensions(prhs[0]); dims = mxGetDimensions(prhs[0]); for (ifield = 0; ifield < nfields; ifield++) { /* Create cell/numeric array */ if (classIDflags[ifield] == mxCHAR_CLASS) { fout = mxCreateCellArray(ndim, dims); } else { fout = mxCreateNumericArray(ndim, dims, classIDflags[ifield], mxREAL); pdata = mxGetData(fout); } /* Copy data from input structure array */ for (jstruct = 0; jstruct < NStructElems; jstruct++) { tmp = mxGetFieldByNumber(prhs[0],jstruct,ifield); if (mxIsChar(tmp)) { mxSetCell(fout, jstruct, mxDuplicateArray(tmp)); } else { size_t sizebuf; sizebuf = mxGetElementSize(tmp); memcpy(pdata, mxGetData(tmp), sizebuf); pdata += sizebuf; } } /* Set each field in output structure */ mxSetFieldByNumber(plhs[0], 0, ifield, fout); } mxFree(classIDflags); return; }
To see how this program works, enter this structure.
friends(1).name = 'Jordan Robert'; friends(1).phone = 3386; friends(2).name = 'Mary Smith'; friends(2).phone = 3912; friends(3).name = 'Stacy Flora'; friends(3).phone = 3238; friends(4).name = 'Harry Alpert'; friends(4).phone = 3077;
Passing Two or More Inputs or Outputs | Handling Complex Data |