/* ========================================================================== * 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 1984-2011 The MathWorks, Inc. *==========================================================================*/ #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 mwSize *dims; mxArray *tmp, *fout; char *pdata=NULL; int ifield, nfields; mxClassID *classIDflags; mwIndex jstruct; mwSize NStructElems; mwSize ndim; /* check proper input and output */ if(nrhs!=1) mexErrMsgIdAndTxt( "MATLAB:phonebook:invalidNumInputs", "One input required."); else if(nlhs > 1) mexErrMsgIdAndTxt( "MATLAB:phonebook:maxlhs", "Too many output arguments."); else if(!mxIsStruct(prhs[0])) mexErrMsgIdAndTxt( "MATLAB:phonebook:inputNotStruct", "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(mxClassID)); /* check empty field, proper data type, and data type consistency; * and 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); mexErrMsgIdAndTxt( "MATLAB:phonebook:fieldEmpty", "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); mexErrMsgIdAndTxt( "MATLAB:phonebook:invalidField", "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); mexErrMsgIdAndTxt( "MATLAB:phonebook:invalidFieldType", "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); mexErrMsgIdAndTxt( "MATLAB:phonebook:fieldNotRealScalar", "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((void *)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 { mwSize 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; }