C ソース MEX ファイル arrayProduct.c の作成
この例では、C 行列 APIで定義された MATLAB® 配列を使用して、MATLAB で C 関数 arrayProduct を呼び出す MEX ファイルを作成する方法を説明します。ソース ファイル全体は、ここで参照できます。
この例を使用するには、以下が必要です。
C または C++ ソース コードを記述する機能。これらのファイルは MATLAB エディターで作成します。
MATLAB でサポートされるコンパイラ。サポートされているコンパイラの最新の一覧については、サポートされるコンパイラ Web サイトを参照してください。
mexビルド スクリプト。
独自の C 開発環境を使用する場合は、MEX スクリプト オプションによるカスタム ビルドで詳細を参照してください。
C 関数 arrayProduct
次のコードは、1 行 N 列の行列 y をスカラー値 x で乗算し、結果を配列 z に返す関数 arrayProduct を定義します。これらの C ステートメントは C++ アプリケーションでも使用できます。
void arrayProduct(double x, double *y, double *z, int n)
{
int i;
for (i=0; i<n; i++) {
z[i] = x * y[i];
}
}
ソース ファイルの作成
MATLAB エディターを開いてファイルを作成し、次の情報を含む MEX ファイルをドキュメント化します。
/* * arrayProduct.c - example in MATLAB External Interfaces * * Multiplies an input scalar (multiplier) * times a 1xN matrix (inMatrix) * and outputs a 1xN matrix (outMatrix) * * The calling syntax is: * * outMatrix = arrayProduct(multiplier, inMatrix) * * This is a MEX file for MATLAB. */
MATLAB API 関数の宣言を含む C/C++ ヘッダー ファイル mex.h を追加します。
#include "mex.h"
たとえば c:\work などの MATLAB パス上にファイルを保存し、arrayProduct.c という名前を付けます。MEX ファイルの名前は arrayProduct です。
ゲートウェイ ルーチンの作成
すべての C プログラムには関数 main() があります。MATLAB は、関数のエントリ ポイントとしてゲートウェイ ルーチン mexFunction を使用します。以下に示す mexFunction のコードを追加します。
/* The gateway function */
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
/* variable declarations here */
/* code here */
}
次の表では、mexFunction の入力パラメーターについて説明します。
| パラメーター | 説明 |
|---|---|
nlhs | 出力 (左辺) 引数の数、つまり配列 plhs のサイズ。 |
plhs | 出力引数の配列。 |
nrhs | 入力 (右辺) 引数の数、つまり配列 prhs のサイズ。 |
prhs | 入力引数の配列。 |
MEX ファイルの入出力パラメーターの確認
nrhs および nlhs 引数を使用して、MEX ファイルの入出力引数の数を確認します。
入力引数が 2 つ (multiplier と inMatrix) であることを確認するには、次のコードを使用します。
if(nrhs != 2) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs",
"Two inputs required.");
}
次のコードを使用して、出力引数が 1 つ (積 outMatrix) であることを確認します。
if(nlhs != 1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs",
"One output required.");
}
plhs および prhs 引数を使用して、引数の型を確認します。このコードでは、prhs[0] で表される multiplier がスカラーであることを確認します。
/* make sure the first input argument is scalar */
if( !mxIsDouble(prhs[0]) ||
mxIsComplex(prhs[0]) ||
mxGetNumberOfElements(prhs[0]) != 1 ) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notScalar",
"Input multiplier must be a scalar.");
}
このコードでは、prhs[1] で表される inMatrix が double 型であることを確認します。
if( !mxIsDouble(prhs[1]) ||
mxIsComplex(prhs[1])) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notDouble",
"Input matrix must be type double.");
}
inMatrix が行ベクトルであることを確認します。
/* check that number of rows in second input argument is 1 */
if(mxGetM(prhs[1]) != 1) {
mexErrMsgIdAndTxt("MyToolbox:arrayProduct:notRowVector",
"Input must be a row vector.");
}計算ルーチンの作成
arrayProduct のコードを追加します。この関数は "計算ルーチン" です。計算ルーチンとは、MATLAB で使用する機能を実行するソース コードのことです。
void arrayProduct(double x, double *y, double *z, int n)
{
int i;
for (i=0; i<n; i++) {
z[i] = x * y[i];
}
}
計算ルーチンはオプションです。このコードは mexFunction Function ブロックの中に置くこともできます。
プラットフォーム間の柔軟性を高めるためのコードの記述
MATLAB は、プリプロセッサ マクロ mwsize を提供しています。これは、プラットフォームを基に整数のサイズの値を表します。計算ルーチンでは配列のサイズを int として宣言しています。この変数 n と i の int 宣言を mwsize に置き換えます。
void arrayProduct(double x, double *y, double *z, mwSize n)
{
mwSize i;
for (i=0; i<n; i++) {
z[i] = x * y[i];
}
}
計算ルーチンの変数の宣言
次の変数宣言を mexFunction に入れます。
入力引数の変数を宣言します。
double multiplier; /* input scalar */ double *inMatrix; /* 1xN input matrix */
入力行列のサイズの
ncolsを宣言します。mwSize ncols; /* size of matrix */
出力引数
outMatrixを宣言します。double *outMatrix; /* output matrix */
後に、mexFunction の引数をこれらの変数に代入します。
入力データの読み取り
スカラー入力を読み取るには、関数 mxGetScalar を使用します。
/* get the value of the scalar input */ multiplier = mxGetScalar(prhs[0]);
関数 mxGetDoubles を使用して、入力行列データを指します。
/* create a pointer to the real data in the input matrix */ inMatrix = mxGetDoubles(prhs[1]);
関数 mxGetN を使用して、行列のサイズを取得します。
/* get dimensions of the input matrix */ ncols = mxGetN(prhs[1]);
出力データの準備
出力引数 plhs[0] を作成するには、関数 mxCreateDoubleMatrix を使用します。
/* create the output matrix */ plhs[0] = mxCreateDoubleMatrix(1,ncols,mxREAL);
関数 mxGetDoubles を使用して、outMatrix 引数を plhs[0] に代入します。
/* get a pointer to the real data in the output matrix */ outMatrix = mxGetDoubles(plhs[0]);
計算の実行
引数を arrayProduct に渡します。
/* call the computational routine */ arrayProduct(multiplier,inMatrix,outMatrix,ncols);
ソース ファイル全体の表示
に存在する matlabroot/extern/examples/mexarrayProduct.c とソース ファイルを比較します。エディターでファイル arrayProduct.c を開きます。
C++ 用の MATLAB データ APIを使用する C++ MEX ファイルの例については、arrayProduct.cpp を参照してください。この API での MEX ファイル作成の詳細については、C++ MEX 関数を参照してください。
MEX 関数のビルド
MATLAB コマンド プロンプトで、mex コマンドを使用して関数をビルドします。
mex arrayProduct.c -R2018a
MEX 関数のテスト
s = 5; A = [1.5, 2, 9]; B = arrayProduct(s,A)
B =
7.5000 10.0000 45.0000
MEX ファイルの入力引数の検証
MEX 関数を呼び出す前に、MATLAB 変数の型を検証することをお勧めします。入力変数 inputArg をテストし、必要に応じてそれを double 型に変換するには、次のコードを使用します。
s = 5; A = [1.5, 2, 9]; inputArg = int16(A); if ~strcmp(class(inputArg),'double') inputArg = double(inputArg); end B = arrayProduct(s,inputArg)
参考
mex | mexFunction | mxCreateDoubleMatrix