[MATLAB] MEX関数の作成方法


はじめに

MEX関数とは、MEXファイルに定義されたC/C++/Fortranで書かれた関数のことで、主にプログラムの高速化のために用いられます。通常のMATLAB関数と同様にMEX関数を読み込んで実行することができます。

以前、MEXファイルを作成したことがあったので、備忘録に残しておきます。
以下ではC++の場合のみ解説します。

MEXファイルのC/C++用API

MEXファイルは必ず以下の形式を取ります。

mexcpp.cpp
#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関数をビルドします。

参考リンク