MATLAB Language
Inleiding tot MEX API
Zoeken…
Controleer aantal ingangen / uitgangen in een C ++ MEX-bestand
In dit voorbeeld zullen we een basisprogramma schrijven dat het aantal ingangen en uitgangen controleert dat wordt doorgegeven aan een MEX-functie.
Om te beginnen moeten we een C ++ -bestand maken dat de "MEX-gateway" implementeert. Dit is de functie die wordt uitgevoerd wanneer het bestand wordt aangeroepen vanuit 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.");
}
}
Eerst nemen we de kop mex.h
die definities bevat van alle vereiste functies en gegevenstypen om met de MEX API te werken. Vervolgens implementeren we de functie mexFunction
zoals weergegeven, waarbij de handtekening niet mag veranderen, onafhankelijk van de feitelijk gebruikte ingangen / uitgangen. De functieparameters zijn als volgt:
-
nlhs
: aantal gevraagde uitgangen. -
*plhs[]
: array met alle uitgangen in MEX API-indeling. -
nrhs
: aantal ingevoerde ingangen. -
*prhs[]
: array met alle ingangen in MEX API-indeling.
Vervolgens controleren we het aantal mexErrMsgIdAndTxt
en als de validatie mislukt, wordt er een fout gegenereerd met de functie mexErrMsgIdAndTxt
(er wordt mexErrMsgIdAndTxt
verwacht somename:iD
indeling, een eenvoudige "ID" werkt niet).
Zodra het bestand is gecompileerd als mex testinputs.cpp
, kan de functie in MATLAB worden opgeroepen als:
>> 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.
Voer een tekenreeks in, wijzig deze in C en voer deze uit
In dit voorbeeld illustreren we stringmanipulatie in MATLAB MEX. We zullen een MEX-functie maken die een string als invoer van MATLAB accepteert, de gegevens naar de C-string kopiëren, wijzigen en terug naar mxArray
converteren naar de MATLAB-zijde.
Het hoofddoel van dit voorbeeld is om te laten zien hoe tekenreeksen kunnen worden geconverteerd naar C / C ++ van MATLAB en vice versa.
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);
}
De relevante functies in dit voorbeeld zijn:
-
mxIsChar
om te testen of eenmxArray
ismxCHAR
soort. -
mxArrayToString
om de gegevens van eenmxArray
reeks naar eenchar *
-buffer te kopiëren. -
mxCreateString
om eenmxArray
string te maken van eenchar*
.
Als een kanttekening, als u alleen de string wilt lezen en deze niet wilt wijzigen, vergeet dan niet deze als const char*
voor snelheid en robuustheid.
Ten slotte kunnen we het, eenmaal gecompileerd, vanuit MATLAB noemen als:
>> mex stringIO.cpp
>> strOut = stringIO('theOneString')
strOut =
TheOneString
>> strOut = stringIO('somethingelse')
strOut=
omethingelse
Geef een 3D-matrix door van MATLAB naar C
In dit voorbeeld illustreren we hoe u een dubbele real-type 3D-matrix van MATLAB neemt en deze doorgeeft aan een C double*
array.
De belangrijkste doelstellingen van dit voorbeeld laten zien hoe gegevens kunnen worden verkregen uit MATLAB MEX-arrays en hoe enkele kleine details in matrixopslag en -verwerking kunnen worden benadrukt.
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;
}
De relevante concepten om op te letten:
MATLAB-matrices zijn allemaal 1D in het geheugen, ongeacht hoeveel dimensies ze hebben wanneer ze in MATLAB worden gebruikt. Dit geldt ook voor de meeste (zo niet alle) hoofdmatrixrepresentatie in C / C ++ - bibliotheken, omdat optimalisatie en snellere uitvoering mogelijk is.
U moet de matrices expliciet in een lus van MATLAB naar C kopiëren.
MATLAB-matrices worden opgeslagen in hoofdvolgorde van kolommen, zoals in Fortran, maar C / C ++ en de meeste moderne talen zijn rij-groot. Het is belangrijk om de invoermatrix toe te staan, anders zien de gegevens er compleet anders uit.
De relevante functie in dit voorbeeld is:
-
mxIsDouble
controle of invoerdouble
is. -
mxIsComplex
controleert of invoer reëel of denkbeeldig is. -
mxGetData
retourneert een pointer naar de echte gegevens in demxGetData
.NULL
als er geen echte gegevens zijn. -
mxGetDimensions
retourneert een pointer naar eenmwSize
array, met de grootte van de dimensie in elke index.
Een struct doorgeven aan veldnamen
Dit voorbeeld illustreert hoe struct-ingangen van het verschillende type uit MATLAB kunnen worden gelezen en doorgegeven aan variabelen van het type C-equivalent.
Hoewel het mogelijk en gemakkelijk is om uit het voorbeeld te achterhalen hoe velden op getallen kunnen worden geladen, wordt dit hier bereikt door de veldnamen met strings te vergelijken. De struct-velden kunnen dus worden geadresseerd door hun veldnamen en variabelen daarin kunnen worden gelezen door 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);
}
}
}
De lus over i
loopt over elk veld in de gegeven struct, terwijl de if(0==strcmp)
de naam van het matlab-veld vergelijken met de gegeven string. Als het een overeenkomst is, wordt de overeenkomstige waarde geëxtraheerd naar een C-variabele.