サーチ…


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変数に抽出されます。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow