| 外部インタフェース/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]
| 複数の入出力を渡す | 複素データの操作 | ![]() |