外部インタフェース/API | ![]() ![]() |
構造体とセル配列を渡す
構造体とセル配列は、MATLAB 5での新しいデータタイプです。構造体とセル配列の機能の説明や、それらの操作のための組み込み関数の説明は、「構造体とセル配列」を参照してください。MATLABの他のすべてのデータタイプのように、構造体とセル配列は、C MEX-ファイルに渡されます。
構造体やセル配列をMEX-ファイルに渡すことは、データ自身がタイプmxArray
であることを除き、他のデータタイプを渡すことと似ています。実際には、これはmxGetField
(構造体)とmxGetCell
(セル配列) がタイプmxArray
のポインタを出力することを意味します。このポインタをタイプmxArray
の他のポインタのように扱うことができますが、mxArray
に含まれるデータをCルーチンに渡したい場合は、アクセスのためにmxGetData
のようなAPI関数を使う必要があります。
つぎの例は、m行n列の構造体行列を入力として受け取り、以下のフィールドをもつ1行1列の構造体を出力します。
int
, double
等のような同じクラスIDをもつm行n列の数値のベクトルを生成します。* ============================================================= * 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.6 $ */ #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; }
このプログラムの動作方法を見るためには、以下の構造体を入力します。
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;
phonebook(friends) ans = name: {1x4 cell } phone: [3386 3912 3238 3077]
![]() | 複数の入出力を渡す | 複素データの操作 | ![]() |