MATLAB Language
Einführung in die MEX-API
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 einmxArray
von istmxCHAR
Typ. -
mxArrayToString
um die Daten einermxArray
Zeichenfolge in einenchar *
mxArrayToString
zu kopieren. -
mxCreateString
ein erstellenmxArray
String aus einemchar*
.
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 Eingabedouble
. -
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 einmwSize
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.