はじめに
MEX関数とは、MEXファイルに定義されたC/C++/Fortranで書かれた関数のことで、主にプログラムの高速化のために用いられます。通常のMATLAB関数と同様にMEX関数を読み込んで実行することができます。
以前、MEXファイルを作成したことがあったので、備忘録に残しておきます。
以下ではC++の場合のみ解説します。
MEXファイルのC/C++用API
MEXファイルは必ず以下の形式を取ります。
#include <mex.h>
/* ... */
// nlhs = 戻り値の数
// plhs = 戻り値へのポインタの配列
// nrhs = 引数の数
// prhs = 引数へのポインタの配列
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]){
/* ... */
}
上に示すMEXプログラムをビルドするとmexcpp
というMEX関数が作られ、MATLABスクリプト内で
<戻り値> = mexcpp(<引数>)
と使用することができます。ファイル内のmexFunction
ではなく、MEXファイル名がMEX関数名となることに注意しましょう。
mexFunction
内では、まず引数・戻り値の数と型を確認します。
// 引数の数が1つかどうか確認
if (nrhs != 1) {
mexErrMsgIdAndTxt("MATLAB:test:mexcpp:nrhs",
"Only one input argument required.");
}
// 第一引数の型がdoubleかどうか確認
if (!mxIsDouble(prhs[0])) {
mexErrMsgIdAndTxt("MATLAB:test:mexcpp:prhs",
"Input argument must be double.");
}
戻り値の数および型も同様に検証します。引数および戻り値の型を検証する関数は
MathWorks Documentation: C行列ライブラリAPI - データの検証
にまとめられています。
次に与えられた引数および戻り値へアクセスします。第一引数にdouble型のスカラーが、第二引数にdouble型の行列が与えられたとすると、以下のようにアクセスすることができます。
// 第一引数
double value = mxGetScalar(prhs[0]);
// 第二引数
// 配列の先頭へのポインタ
double* data = mxGetPr(prhs[1]);
// 第二引数の行・列数を得る
size_t rows = mxGetM(prhs[1]);
size_t cols = mxGetN(prhs[1]);
MATLABクラスのオブジェクトを渡してそのデータメンバーにアクセスすることも可能です。(mxGetProperty
を使う)
データへアクセス(読み込み・書き込み)するための関数は
MathWorks Documentation: C行列ライブラリAPI - データへのアクセス
にまとめられています。
あとは得られたデータを使って戻り値を計算するだけです。
配列を扱う場合は、得られた生ポインタを適当なラッパークラスでラップしてから使用しましょう。(線形代数の計算を行うならEigen::Map
を使うと便利です。単なる配列ならgsl::span
でよいでしょう。)
MEXファイルができたらmex
コマンドを使ってMEX関数をビルドします。
参考リンク
- MathWorks Documentation