Sök…


Kontrollera antalet ingångar / utgångar i en C ++ MEX-fil

I det här exemplet kommer vi att skriva ett grundläggande program som kontrollerar antalet ingångar och utgångar som skickas till en MEX-funktion.

Som utgångspunkt måste vi skapa en C ++ -fil som implementerar "MEX-gatewayen". Detta är den funktion som körs när filen anropas från 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.");
    }
}

Först inkluderar vi mex.h huvudet som innehåller definitioner av alla nödvändiga funktioner och datatyper för att fungera med MEX API. Sedan implementerar vi funktionen mexFunction som visas, där dess signatur inte får ändras, oberoende av de ingångar / utgångar som faktiskt används. Funktionsparametrarna är som följer:

  • nlhs : Antal begärda utgångar.
  • *plhs[] : Array som innehåller alla utgångar i MEX API-format.
  • nrhs : Antal ingångar som gått.
  • *prhs[] : Array som innehåller alla ingångar i MEX API-format.

Därefter kontrollerar vi antalet argument för ingångar / utgångar, och om valideringen misslyckas kastas ett fel med funktionen mexErrMsgIdAndTxt (den förväntar sig ett somename:iD , en enkel "ID" fungerar inte).


När filen har sammanställts som mex testinputs.cpp kan funktionen kallas i MATLAB som:

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

Mata in en sträng, ändra den i C och mata ut den

I det här exemplet illustrerar vi strängmanipulation i MATLAB MEX. Vi skapar en MEX-funktion som accepterar en sträng som inmatning från MATLAB, kopierar data till C-sträng, modifierar den och konverterar den tillbaka till mxArray returneras till MATLAB-sidan.

Huvudmålet med detta exempel är att visa hur strängar kan konverteras till C / C ++ från MATLAB och 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 relevanta funktionerna i detta exempel är:

  • mxIsChar att testa om en mxArray är av mxCHAR typ.
  • mxArrayToString att kopiera data från en mxArray sträng till en char * -buffert.
  • mxCreateString att skapa en mxArray sträng från en char* .

Som sidoanteckning, om du bara vill läsa strängen och inte ändra den, kom ihåg att förklara den som const char* för hastighet och robusthet.


Slutligen, när vi har sammanställts kan vi kalla det från MATLAB som:

>> mex stringIO.cpp

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

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

Skicka en 3D-matris från MATLAB till C

I det här exemplet illustrerar vi hur man tar en dubbel realtyp 3D-matris från MATLAB och överför den till en C double* matris.

Huvudmålen för detta exempel är att visa hur man får data från MATLAB MEX-matriser och att lyfta fram några små detaljer i matrislagring och hantering.

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 relevanta begreppen att vara medvetna om:

  • MATLAB-matriser är alla 1D i minnet, oavsett hur många dimensioner de har när de används i MATLAB. Detta är också sant för de flesta (om inte alla) huvudmatrisrepresentation i C / C ++ -bibliotek, vilket möjliggör optimering och snabbare körning.

  • Du måste uttryckligen kopiera matriser från MATLAB till C i en slinga.

  • MATLAB-matriser lagras i huvudordning i kolumnen, som i Fortran, men C / C ++ och de flesta moderna språk är rad major. Det är viktigt att tillåta inmatningsmatrisen, annars kommer data att se helt annorlunda ut.

Den relevanta funktionen i detta exempel är:

  • mxIsDouble kontrollerar om ingången är av double typ.
  • mxIsComplex kontrollerar om ingången är verklig eller imaginär.
  • mxGetData returnerar en pekare till de verkliga data i inmatningsfältet. NULL om det inte finns några verkliga data.
  • mxGetDimensions returnerar en pekare till en mwSize matris med storleken på dimensionen i varje index.

Att skicka en struktur efter fältnamn

Det här exemplet illustrerar hur man läser strukturposter av olika slag från MATLAB och skickar det till C-ekvivalenta typvariabler.

Även om det är möjligt och enkelt att ta reda på exemplet hur man laddar fält med siffror, uppnås det här genom att jämföra fältnamn med strängar. Således kan strukturfälten adresseras av deras fältnamn och variabler i det kan läsas av 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);
    }
  }
}

Loopen över i kör över varje fält i den givna strukturen, medan if(0==strcmp) -delarna jämför matlabfältets namn med den givna strängen. Om det är en matchning extraheras motsvarande värde till en C-variabel.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow