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 een mxArray is mxCHAR soort.
  • mxArrayToString om de gegevens van een mxArray reeks naar een char * -buffer te kopiëren.
  • mxCreateString om een mxArray string te maken van een char* .

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 invoer double is.
  • mxIsComplex controleert of invoer reëel of denkbeeldig is.
  • mxGetData retourneert een pointer naar de echte gegevens in de mxGetData . NULL als er geen echte gegevens zijn.
  • mxGetDimensions retourneert een pointer naar een mwSize 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.



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow