Suche…


Prüfen Sie die Anzahl der Ein- / Ausgänge in einer C ++ MEX-Datei

In diesem Beispiel schreiben wir ein Basisprogramm, das die Anzahl der Ein- und Ausgänge prüft, die an eine MEX-Funktion übergeben werden.

Als Ausgangspunkt müssen wir eine C ++ - Datei erstellen, die das "MEX-Gateway" implementiert. Dies ist die Funktion, die ausgeführt wird, wenn die Datei von MATLAB aufgerufen wird.

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.");
    }
}

Zuerst mex.h wir den mex.h Header hinzu, der Definitionen aller erforderlichen Funktionen und Datentypen enthält, um mit der MEX-API zu arbeiten. Dann implementieren wir die Funktion mexFunction wie gezeigt, wobei sich ihre Signatur unabhängig von den tatsächlich verwendeten Ein- / Ausgängen nicht ändern darf. Die Funktionsparameter lauten wie folgt:

  • nlhs : Anzahl der angeforderten Ausgaben.
  • *plhs[] : Array, das alle Ausgaben im MEX-API-Format enthält.
  • nrhs : Anzahl der übergebenen Eingänge.
  • *prhs[] : Array, das alle Eingaben im MEX-API-Format enthält.

Als Nächstes überprüfen wir die Anzahl der somename:iD Wenn die Überprüfung fehlschlägt, wird mit der Funktion mexErrMsgIdAndTxt ein Fehler mexErrMsgIdAndTxt (es erwartet einen somename:iD Formatbezeichner, eine einfache "ID" funktioniert nicht).


Nachdem die Datei als mex testinputs.cpp kompiliert wurde, kann die Funktion in MATLAB wie mex testinputs.cpp aufgerufen werden:

>> 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.

Geben Sie einen String ein, ändern Sie ihn in C und geben Sie ihn aus

In diesem Beispiel wird die Bearbeitung von Strings in MATLAB MEX veranschaulicht. Wir werden eine MEX-Funktion erstellen, die eine Zeichenfolge als Eingabe von MATLAB akzeptiert, die Daten in C-Zeichenfolge kopieren, ändern und zurück in mxArray konvertieren, mxArray an die MATLAB-Seite zurückgegeben wird.

Das Hauptziel dieses Beispiels ist es zu zeigen, wie Strings von MATLAB nach C / C ++ konvertiert werden können und umgekehrt.

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);
}

Die relevanten Funktionen in diesem Beispiel sind:

  • mxIsChar zu testen , ob ein mxArray von ist mxCHAR Typ.
  • mxArrayToString um die Daten einer mxArray Zeichenfolge in einen char * mxArrayToString zu kopieren.
  • mxCreateString ein erstellen mxArray String aus einem char* .

Wenn Sie die Zeichenfolge nur lesen und nicht ändern möchten, müssen Sie sie als const char* für Geschwindigkeit und Robustheit deklarieren.


Nach dem Kompilieren können wir es schließlich von MATLAB nennen:

>> mex stringIO.cpp

>> strOut = stringIO('theOneString')
strOut = 
TheOneString

>> strOut = stringIO('somethingelse')
strOut=
omethingelse

Übergeben Sie eine 3D-Matrix von MATLAB an C

In diesem Beispiel wird gezeigt, wie eine echte 3D-Matrix vom Typ MATLAB an ein C double* -Array übergeben wird.

Die Hauptziele dieses Beispiels zeigen, wie man Daten von MATLAB MEX-Arrays erhält und einige kleine Details bei der Matrixspeicherung und -behandlung hervorhebt.

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;
}

Die relevanten Konzepte zu beachten:

  • MATLAB-Matrizen sind alle 1D im Speicher, unabhängig davon, wie viele Dimensionen sie in MATLAB haben. Dies gilt auch für die meisten (wenn nicht alle) Hauptmatrixdarstellungen in C / C ++ - Bibliotheken, da sie eine Optimierung und eine schnellere Ausführung ermöglichen.

  • Sie müssen Matrizen in einer Schleife explizit von MATLAB nach C kopieren.

  • MATLAB-Matrizen werden wie in Fortran in der Reihenfolge der Spalten gespeichert, aber C / C ++ und die meisten modernen Sprachen sind Zeilenreihen. Es ist wichtig, die Eingabematrix zu permutieren, da sonst die Daten völlig anders aussehen.

Die relevanten Funktionen in diesem Beispiel sind:

  • mxIsDouble prüft, ob die Eingabe double .
  • mxIsComplex prüft, ob die Eingabe real oder imaginär ist.
  • mxGetData gibt einen Zeiger auf die realen Daten im Eingabearray zurück. NULL wenn keine echten Daten vorhanden sind.
  • mxGetDimensions gibt einen Zeiger auf ein mwSize Array mit der Größe der Dimension in jedem Index zurück.

Übergeben einer Struktur nach Feldnamen

Dieses Beispiel zeigt, wie Sie Struktureinträge verschiedener Typen aus MATLAB lesen und an C-äquivalente Typvariablen übergeben.

Während es möglich und einfach ist, aus dem Beispiel herauszufinden, wie Felder durch Zahlen geladen werden, wird dies hier durch Vergleich der Feldnamen mit Zeichenfolgen erreicht. Somit können die Strukturfelder mit ihren Feldnamen angesprochen und die darin enthaltenen Variablen von C gelesen werden.

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);
    }
  }
}

Die Schleife über i läuft über jedes Feld in der angegebenen Struktur, während die if(0==strcmp) -Parts den Namen des Matlab-Felds mit der angegebenen Zeichenfolge vergleichen. Wenn es eine Übereinstimmung ist, wird der entsprechende Wert in eine C-Variable extrahiert.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow