MATLAB Language
MEX APIの紹介
サーチ…
C ++ MEXファイルの入力/出力数を確認する
この例では、MEX関数に渡される入力と出力の数をチェックする基本的なプログラムを記述します。
出発点として、「MEXゲートウェイ」を実装するC ++ファイルを作成する必要があります。これは、ファイルがMATLABから呼び出されたときに実行される関数です。
testinputs.cpp
// MathWorks provided header file
#include "mex.h"
// gateway function
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
// This function will error if number of inputs its not 3 or 4
// This function will error if number of outputs is more than 1
// Check inputs:
if (nrhs < 3 || nrhs > 4) {
mexErrMsgIdAndTxt("Testinputs:ErrorIdIn",
"Invalid number of inputs to MEX file.");
}
// Check outputs:
if (nlhs > 1) {
mexErrMsgIdAndTxt("Testinputs:ErrorIdOut",
"Invalid number of outputs to MEX file.");
}
}
最初に、MEX APIを使用するために必要なすべての関数とデータ型の定義を含むmex.h
ヘッダーをmex.h
ます。次に、実際に使用される入力/出力とは関係なく、その署名が変更されてはならないmexFunction
関数を示します。関数のパラメータは次のとおりです。
-
nlhs
:要求された出力の数。 -
*plhs[]
:MEX API形式のすべての出力を含む配列。 -
nrhs
:渡された入力の数。 -
*prhs[]
:MEX API形式のすべての入力を含む配列。
次に、入出力の引数の数を確認し、検証に失敗した場合は、 mexErrMsgIdAndTxt
関数を使用してエラーがスローされます( somename:iD
形式識別子が必要で、単純な「ID」は機能しません)。
ファイルがmex testinputs.cpp
としてコンパイルされると、この関数はMATLABで次のように呼び出すことができます。
>> testinputs(2,3)
Error using testinputs. Invalid number of inputs to MEX file.
>> testinputs(2,3,5)
>> [~,~] = testinputs(2,3,3)
Error using testinputs. Invalid number of outputs to MEX file.
文字列を入力し、Cで修正して出力する
この例では、MATLAB MEXでの文字列操作を示します。文字列をMATLABから入力として受け取り、データをC文字列にコピーし、修正し、MATLAB側に返されたmxArray
に変換するMEX関数を作成します。
この例の主な目的は、MATLABから文字列をC / C ++に変換する方法とその逆を示すことです。
stringIO.cpp
#include "mex.h"
#include <cstring>
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
// check number of arguments
if (nrhs != 1 || nlhs > 1) {
mexErrMsgIdAndTxt("StringIO:WrongNumArgs", "Wrong number of arguments.");
}
// check if input is a string
if (mxIsChar(prhs[0])) {
mexErrMsgIdAndTxt("StringIO:TypeError", "Input is not a string");
}
// copy characters data from mxArray to a C-style string (null-terminated)
char *str = mxArrayToString(prhs[0]);
// manipulate the string in some way
if (strcmp("theOneString", str) == 0) {
str[0] = 'T'; // capitalize first letter
} else {
str[0] = ' '; // do something else?
}
// return the new modified string
plhs[0] = mxCreateString(str);
// free allocated memory
mxFree(str);
}
この例の関連する関数は次のとおりです。
-
mxIsChar
かどうかをテストするためmxArray
であるmxCHAR
タイプ。 -
mxArrayToString
のデータをコピーするmxArray
に文字列をchar *
バッファ。 -
mxCreateString
を使用して、char*
からmxArray
文字列を作成しmxArray
。
補足として、文字列を読み込み、変更しない場合は、速度と堅牢性のためにconst char*
として宣言してください。
最後に、一度コンパイルすると、MATLABから次のように呼び出すことができます。
>> mex stringIO.cpp
>> strOut = stringIO('theOneString')
strOut =
TheOneString
>> strOut = stringIO('somethingelse')
strOut=
omethingelse
MATLABから3D行列をCに渡す
この例では、MATLABからdouble型の実数型3D行列を取得し、それをC double*
配列に渡す方法を示します。
この例の主な目的は、MATLAB MEXアレイからデータを取得する方法と、行列の保存と処理の細部を強調する方法を示しています。
matrixIn.cpp
#include "mex.h"
void mexFunction(int nlhs , mxArray *plhs[],
int nrhs, mxArray const *prhs[]){
// check amount of inputs
if (nrhs!=1) {
mexErrMsgIdAndTxt("matrixIn:InvalidInput", "Invalid number of inputs to MEX file.");
}
// check type of input
if( !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0])){
mexErrMsgIdAndTxt("matrixIn:InvalidType", "Input matrix must be a double, non-complex array.");
}
// extract the data
double const * const matrixAux= static_cast<double const *>(mxGetData(prhs[0]));
// Get matrix size
const mwSize *sizeInputMatrix= mxGetDimensions(prhs[0]);
// allocate array in C. Note: its 1D array, not 3D even if our input is 3D
double* matrixInC= (double*)malloc(sizeInputMatrix[0] *sizeInputMatrix[1] *sizeInputMatrix[2]* sizeof(double));
// MATLAB is column major, not row major (as C). We need to reorder the numbers
// Basically permutes dimensions
// NOTE: the ordering of the loops is optimized for fastest memory access!
// This improves the speed in about 300%
const int size0 = sizeInputMatrix[0]; // Const makes compiler optimization kick in
const int size1 = sizeInputMatrix[1];
const int size2 = sizeInputMatrix[2];
for (int j = 0; j < size2; j++)
{
int jOffset = j*size0*size1; // this saves re-computation time
for (int k = 0; k < size0; k++)
{
int kOffset = k*size1; // this saves re-computation time
for (int i = 0; i < size1; i++)
{
int iOffset = i*size0;
matrixInC[i + jOffset + kOffset] = matrixAux[iOffset + jOffset + k];
}
}
}
// we are done!
// Use your C matrix here
// free memory
free(matrixInC);
return;
}
認識すべき関連概念:
MATLABの行列は、MATLABで使用された場合の次元数にかかわらず、メモリ上のすべて1Dです。これは、C / C ++ライブラリのほとんどの(すべてではないにせよ)メイン・マトリックス表現にも当てはまります。最適化と高速実行が可能です。
ループ内でMATLABからCに行列を明示的にコピーする必要があります。
MATLABの行列は、Fortranのように列の大部分の順序で格納されますが、C / C ++と最も近代的な言語は行の長さです。入力行列を置換することが重要です。そうでなければ、データは完全に異なって見えます。
この例の関連する関数は次のとおりです。
-
mxIsDouble
は、入力がdouble
型かどうかをチェックします。 -
mxIsComplex
は、入力が実数か虚数かをチェックします。 -
mxGetData
は、入力配列内の実データへのポインタを返します。実際のデータがない場合はNULL
。 -
mxGetDimensions
は、各インデックス内の次元のサイズを持つmwSize
配列へのポインタを返します。
構造体をフィールド名で渡す
この例は、MATLABからさまざまな型の構造体エントリを読み込み、Cの等価型変数に渡す方法を示しています。
この例から、フィールドを数値でロードする方法を理解することは可能ですが、ここではフィールド名を文字列と比較することで実現します。したがって、structフィールドはフィールド名でアドレス指定することができ、その中の変数はCで読み取ることができます。
structIn.c
#include "mex.h"
#include <string.h> // strcmp
void mexFunction (int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
// helpers
double* double_ptr;
unsigned int i; // loop variable
// to be read variables
bool optimal;
int randomseed;
unsigned int desiredNodes;
if (!mxIsStruct(prhs[0])) {
mexErrMsgTxt("First argument has to be a parameter struct!");
}
for (i=0; i<mxGetNumberOfFields(prhs[0]); i++) {
if (0==strcmp(mxGetFieldNameByNumber(prhs[0],i),"randomseed")) {
mxArray *p = mxGetFieldByNumber(prhs[0],0,i);
randomseed = *mxGetPr(p);
}
if (0==strcmp(mxGetFieldNameByNumber(prhs[0],i),"optimal")) {
mxArray *p = mxGetFieldByNumber(prhs[0],0,i);
optimal = (bool)*mxGetPr(p);
}
if (0==strcmp(mxGetFieldNameByNumber(prhs[0],i),"numNodes")) {
mxArray *p = mxGetFieldByNumber(prhs[0],0,i);
desiredNodes = *mxGetPr(p);
}
}
}
if(0==strcmp)
strcmp if(0==strcmp)
-partsは、matlabフィールドの名前と指定された文字列を比較しながら、 i
はループを介して与えられた構造体のすべてのフィールドを実行します。一致する場合は、対応する値がC変数に抽出されます。