MEX文件

Section 8: The ingredients of a MEX-file

All MEX-files must include four things:

  1. #include mex.h (C/C++ MEX-files only)
  2. mexFunction gateway in C/C++ (or SUBROUTINE MEXFUNCTION in Fortran)
  3. The mxArray
  4. API functions


Section 9: mex.h

Every C/C++ MEX-file must include mex.h This is necessary to use the mx* and mex* routines that are discussed in the API functions section of the technical note.

Section 10: mexFunction gateway

The gateway routine to every MEX-file is called mexFunction. This is the entry point MATLAB uses to access the DLL.

In C/C++, it is always:

mexFunction(int nlhs, mxArray *plhs[ ],
int nrhs, const mxArray *prhs[ ]) { . }
                                

In Fortran, it is always:

SUBROUTINE MEXFUNCTION( NLHS, PLHS, NRHS, PRHS) 

Here is what each of the elements mean:

mexFunction Name of the gateway routine (same for every MEX-file)
nlhs Number of expected mxArrays (Left Hand Side)
plhs Array of pointers to expected outputs
nrhs Number of inputs (Right Hand Side)
prhs Array of pointers to input data. The input data is read-only and should not be altered by your mexFunction .

The variables nrhs and nlhs are the number of variables that MATLAB requested at this instance. They are analogous to NARGIN and NARGOUT in MATLAB.

The variables prhs and plhs are not mxArrays. They are arrays of pointers to mxArrays. So if a function is given three inputs, prhs will be an array of three pointers to the mxArrays that contain the data passed in. The variable prhs is declared as const. This means that the values that are passed into the MEX-file should not be altered. Doing so can cause segmentation violations in MATLAB. The values in plhs are invalid when the MEX-file begins. The mxArrays they point to must be explicitly created before they are used. Compilers will not catch this issue, but it will cause incorrect results or segmentation violations.

Section 11: The mxArray

The mxArray is a special structure that contains MATLAB data. It is the C representation of a MATLAB array. All types of MATLAB arrays (scalars, vectors, matrices, strings, cell arrays, etc.) are mxArrays. For a detailed description of an mxArray, see the MATLAB External Interfaces Guide.

The MATLAB language works with only a single object type, the mxArray. All MATLAB variables, including scalars, vectors, matrices, strings, cell arrays, and structures are stored as mxArrays. The mxArray declaration corresponds to the internal data structure that MATLAB uses to represent arrays. The MATLAB array is the C language definition of a MATLAB variable. The mxArray structure contains, among other things:

  1. The MATLAB variable's name
  2. Its dimensions
  3. Its type
  4. Whether the variable is real or complex

If the variable contains complex numbers as elements, the MATLAB array includes vectors containing the real and imaginary parts. Matrices, or m-by-n arrays, that are not sparse are called full. In the case of a full matrix, the mxArray structure contains parameters called pr and pi. pr contains the real part of the matrix data; pi contains the imaginary data, if there is any. Both pr and pi are one-dimensional arrays of double-precision numbers. The elements of the matrix are stored in these arrays column-wise.

An mxArray is declared like any other variable:

mxArray *myarray; 

This creates an mxArray named myarray. The values inside myarray are undefined when it's declared, so it should be initialized with an mx* routine (such as mxCreateNumericArray) before it is used.

It is important to note that the data inside the array is in column major order. Instead of reading a matrix's values across and then down, the values are read down and then across. This is contrary to how C indexing works and means that special care must be taken when accessing the array's elements. To access the data inside of mxArrays, use the API functions (see below).

Section 12: API functions

mx* functions are used to access data inside of mxArrays. They are also used to do memory management and to create and destroy mxArrays. Some useful routines are:

Array creation mxCreateNumericArray, mxCreateCellArray, mxCreateCharArray
Array access mxGetPr, mxGetPi, mxGetM, mxGetData, mxGetCell
Array modification mxSetPr, mxSetPi, mxSetData, mxSetField
Memory management mxMalloc, mxCalloc, mxFree, mexMakeMemoryPersistent, mexAtExit, mxDestroyArray, memcpy

Remember that mxGetPr and mxGetPi return pointers to their data. To change the values in the array, it is necessary to directly change the value in the array pointed at, or use a function like memcpy from the C Standard Library.

#include <string.h>
#include "mex.h"

void mexFunction(int nlhs, mxArray *plhs[ ],int nrhs, const mxArray *prhs[ ]) 
{
int j;
double *output;
double data[] = {1.0, 2.1, 3.0};


/* Create the array */
plhs[0] = mxCreateDoubleMatrix(1,3,mxREAL);
output = mxGetPr(plhs[0]);


/* Populate the output */
memcpy(output, data, 3*sizeof(double));

/* Alternate method to populate the output, one element at a time */
/* for (j = 0; j < 3; j++) */
/* { */
/*   output[j] = data[j]; */
/* } */

}                    

The API functions mxCalloc and mxFree etc. should be used instead of their Standard C counterparts because the mx* routines let MATLAB manage the memory and perform initialization and cleanup.

On the PC there is no concept of stdin, stdout and stderr, so it is important to use MATLAB's functions such as mexPrintf and mexError. A full list of mx* routines with complete descriptions can be found in the MATLAB External/API Reference Guide.

mex* functions perform operations back in MATLAB.

Some useful routines are:

mexFunction Entry point to C MEX-file
mexErrMsgTxt Issue error message and return to MATLAB
mexEvalString  Execute MATLAB command in caller's workspace
mexCallMATLAB  Call MATLAB function or user-defined M-file or MEX-file
mexGetArray Get copy of variable from another workspace
mexPrintf ANSI C printf -style output routine
mexWarnMsgTxt  Issue warning message

A full list of mex* routines with complete descriptions can be found in the MATLAB External/API Reference Guide.

The MEX API provides several functions that allow you to determine various states of an array. These functions are used to check the input to the MEX-file, to make sure it is what's expected. All of these functions begin with the mxIs prefix. In some cases it may be desirable to use the specific mxIs function for a specific datatype. However, it is much easier, in general, to use mxIsClass to perform this operation.

In order to prevent passing inputs that are the incorrect type, use the mxIsClass function extensively at the beginning of your MEX-file. For example, suppose prhs[0] is supposed to be a regular, full, real-valued array. To prevent passing your function a sparse matrix, a string matrix, or a complex matrix, use code similar to the following:

if ( mxIsChar(prhs[0]) || mxIsClass(prhs[0], "sparse") || 
mxIsComplex(prhs[0]) )
mexErrMsgTxt("first input must be real, full, and nonstring"); 

Putting these checks in your code will make your MEX-file more robust. Instead of causing a segmentation fault when passed incorrect arguments, it will instead produce an error message and return you to the MATLAB Command Prompt.

Section 13: Example: Writing a "Hello World" MEX-file

In this first example, we will create a MEX-file (hello.c) that prints "hello world" to the screen. We will then build and run the MEX-file from MATLAB.

  1. As described in the ingredients section, every MEX-file includes mex.h. Thus, your MEX source should start like this:
    #include "mex.h" 
  2. Every MEX-file has the mexFunction entry point. The souce now becomes
    #include "mex.h" 
    void mexFunction(int nlhs, mxArray *plhs[],
        int nrhs, const mxArray *prhs[]) { 
  3. Add an API function to make the MEX-file do something. The final version of the souce becomes:
    #include "mex.h" 
    void mexFunction(int nlhs, mxArray *plhs[],
        int nrhs, const mxArray *prhs[]) {
      mexPrintf("Hello, world!/n"); 
    } 

    Your first MEX-file is complete. Save it as hello.c.

  4. The next step is to tell MATLAB which compiler you want to use to build the MEX-file. You do this with the mex -setup command. You can choose the LCC compiler, the C compiler included with MATLAB. This is what it looks like from the MATLAB command prompt:

     

    mex -setup
    Please choose your compiler for building external interface (MEX) files: 
     
    Would you like mex to locate installed compilers [y]/n?  y
     
    Select a compiler: 
    [1] Lcc C version 2.4.1 in D:/APPLIC~1/MATLAB/R2006b/sys/lcc 
    [2] Microsoft Visual C/C++ version 8.0 in D:/Applications/Microsoft Visual Studio 8 
    [3] Microsoft Visual C/C++ version 7.1 in D:/Applications/Microsoft Visual Studio .NET 2003 
     
    [0] None 
     
    Compiler: 1
     
    Please verify your choices: 
     
    Compiler: Lcc C 2.4.1 
    Location: D:/APPLIC~1/MATLAB/R2006b/sys/lcc 
     
    Are these correct?([y]/n): 
     
    Trying to update options file: 
       C:/WINNT/Profiles/username/Application Data/...
       MathWorks/MATLAB/R2006b/mexopts.bat 
    From template:              
       D:/APPLIC~1/MATLAB/R2006b/bin/win32/mexopts/lccopts.bat 
     
    Done . . . 
    

     

     

  5. Now you are ready to compile and link the MEX-file. You can do this with the following command:
    mex hello.c
    Notice that hello.mexw32 (the MATLAB callable MEX-file for 32-bit Windows) is created in the current directory; MEX-file extensions vary by platform.
  6. You can now call the MEX-file like any other M-file by typing its name at the MATLAB command prompt.
    hello
    Hello, world!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章