Ana səhifə

What is a mex file?


Yüklə 64.5 Kb.
tarix18.07.2016
ölçüsü64.5 Kb.

J. Andrew Johnson 06/27/16

Using Microsoft Visual C++ to develop Matlab MEX file applications

What is a MEX file?


A MEX file is a function which is written in C (or other language) and compiled specifically for use within MATLAB. In Windows 95/98/NT, the compiled module has a file extension .dll. On AIX, the file extension is .mexrs6. Other operating systems use unique extensions as well (including Sun OS, Solaris, Linux, and more).

Advantages


Speed. Compiled MEX programs can run on the order of 100 times faster than an equivalent Matlab script function for some applications.

More information


From Matlab, type helpdesk, and select Application Program Interface hyperlink.
There is also available from The Mathworks, Inc. a book entitled Matlab Application Program Interface Guide.

Compiling


Matlab is shipped with a tool called cmex which can be used to compile a set of C files into a single MEX file. This works well for many applications, but is not conducive to automated compiler builds.
An alternative is to use a development environment, such as Microsoft Visual C++. This is the method that will be described here; it should be easily adapted (except for “Method 1”) to other compiling environments, such as Turbo C.

Method 1


Use the “Matlab Mex Function” Custom App Wizard. There are two files, MexWizard.awx and MexWizard.hlp, which simply get copied to the \Program Files\Microsoft Visual Studio\Common\MSDev98\Template folder.
Now, when you create a new project, you’ll see “Matlab Mex File” appear as one of the project options.
This can be used with existing source code, simply by creating the new project, and then copying your development files into it.
The process should be easy enough that no additional words will be placed here.

Method 2 (Matlab 6.0 and later)


Matlab 6.0 and later is delivered with “mex libraries” (libmx.lib and libmex.lib) already targeted for a variety of different compilers and compiler versions. The section will describe the libraries specific to Microsoft Visual C++ 6.0, but it could be extended to others.
Here is the procedure for creating a mex function:
For purpose of example, Matlab is installed in e:\MATLAB6p1, and the new project name is MyFunction.


  1. From the development environment, create a new Win32 Dynamic-Link Library project (empty). When selecting a project name, I usually end it in “_mex” to differentiate it from a stand alone .exe version.




  1. Once the project MyFunction_mex is created, modify the project settings (shortcut is Alt-F7).

Table 1, Changes to project settings



Tab

Category

Field

Value

Debug

General

Executable for debug session

e:\ MATLAB6p1\bin\win32\matlab.exe

Debug

General

Program Arguments

/nosplash***

C/C++

Preprocessor

Preprocessor definitions

MATLAB_MEX_FILE*

C/C++

Preprocessor

Additional include directories

e:\matlab\extern\include

Link

General

Output file name

MyFunction.dll**

Link

Input

Object/library modules

libmex.lib libmx.lib*

Link

Input

Additional Library Path

e:\MATLAB6p1\extern\lib\win32\microsoft\msvc60

Link

(any)

Project Options

/EXPORT:mexFunction*

*This value should be added to the current list of values

**Note that, by convention, the “_mex” has been truncated. A directory name may be specified, if desired.

***Start MATLAB without displaying the MATLAB splash screen. (optional)


  1. Add C source files to the project, one of which must contain a function called mexFunction. (See below.) That file (and maybe others) should contain the directive

#include “mex.h”

Method 2 (Matlab 5.3 and earlier)


This section describes a method for creating MEX-file projects using Microsoft Visual C++. Two (or more) projects are created in the same workspace. The first project builds the mex libraries (meximports.lib). The second (are successive) projects are your application projects, which link in the mex library.
It is predicated on two features of Visual C++:


  1. Projects can be created which have dependencies on other projects. A separate project is created to build the file “meximports.lib”, which needs to be done only once, regardless of the number of mex-file projects in the workspace.




  1. Linker options can be explicitly added to the link step to define exported functions, eliminating the need for the “MyFuntion_mex.DEF” file.

Here is an overview for creating a mex-file using this method.


First, create a project to build “meximports.lib”:


  1. From the development environment, create a new Win32 Static Library project (empty). Name the project “meximports”. You may opt to “Add to Current Workspace” if you are converting an existing project.




  1. Add a file to the project (by right-clicking on the project name from “File View”), “e:\matlab\extern\include\matlab.def”. (The path may vary depending on where Matlab was installed.)




  1. Modify the settings for the file “matlab.def” as follows:

Table 2, Changes to file settings

Tab

Field

Value

Custom Build

Commands

lib /def:$(InputPath) /machine:ix86 /out:$(TargetPath)

Custom Build

Outputs

$(TargetPath)

Note that the tokens $(InputPath) and $(TargetPath) can be inserted using the select buttons at the bottom of the dialog box.

Next, create a project to build the mex-file, which will have a dependency on the above project:





  1. From the development environment, create a new Win32 Dynamic-Link Library project (empty). Name the project appropriate for your new MEX-file. When creating the project, select the “Add to Current Workspace” radio button, is the project is placed in the same workspace as the meximports.dll project.




  1. Once the project MyFunction_mex is created, modify the project settings (shortcut is Alt-F7).

Table 3, Changes to project settings



Tab

Category

Field

Value

Debug

General

Executable for debug session

e:\matlab\bin\matlab.exe

Debug

General

Program Arguments

/nosplash**

C/C++

Preprocessor

Preprocessor definitions

MATLAB_MEX_FILE*

C/C++

Preprocessor

Additional include directories

e:\matlab\extern\include

Link

Any


Project Options

/EXPORT:mexFunction*

*This value should be added to the current list of values

**Start MATLAB without displaying the MATLAB splash screen. (optional)


  1. From the menu bar, select Project->Dependencies. Make sure the “Select project to modify” field is set to the new mex-file project. In the “Dependent on the following projects” area, mark the checkbox labeled “meximports”.

When the new mex-file project is built, is should first create the meximports.lib file, and then continue building the mex-file project. Note that many mex-file projects in the same workspace can have a dependency on the meximports project.


Method 3


This is the older method I used to use, when I was still “wet behind the ears.” It should still work, and I include it here just for reference.
For purpose of example, Matlab is installed in E:\matlab, and the new project name is MyFunction.


  1. From the development environment, create a new Win32 Dynamic-Link Library project (empty). When selecting a project name, I usually end it in “_mex” to differentiate it from a stand alone .exe version.




  1. Once the project MyFunction_mex is created, modify the project settings (shortcut is Alt-F7).

Table 4, Changes to project settings



Tab

Category

Field

Value

Debug

General

Executable for debug session

e:\matlab\bin\matlab.exe

Debug

General

Program Arguments

/nosplash***

C/C++

Preprocessor

Preprocessor definitions

MATLAB_MEX_FILE*

C/C++

Preprocessor

Additional include directories

e:\matlab\extern\include

Link

General

Output file name

MyFunction.dll**

Link

General

Object/library modules

meximports.lib*

Pre-link step

-

Pre-link command(s)

lib /def:e:\matlab\extern\include\matlab.def /machine:ix86 /out:meximports.lib

*This value should be added to the current list of values

**Note that, by convention, the “_mex” has been truncated. A directory name may be specified, if desired.

***Start MATLAB without displaying the MATLAB splash screen. (optional)


  1. Add a file to the project called MyFunction_mex.def. Type the following contents into the file:

LIBRARY MyFunction.dll

EXPORTS mexFunction





  1. Add C source files to the project, one of which must contain a function called mexFunction. (See below.) That file (and maybe others) should contain the directive

#include “mex.h”

Debugging


The project settings defined in Table 4, Changes to project settings should be sufficient to enable debugging directly from the development environment. Note that it actually invokes Matlab, from which the developer must manually execute the function (MyFunction), or include it in the statrup.m file.
Debugging can also be initiated from a DOS prompt by typing:

msdev E:\matlab\bin\matlab.exe

where msdev is the Microsoft Development Studio, the C development environment, also the function being debugged must be executed once before breakpoints can be set in the C code.


Access violation errors are common during development of a mex application. To trap these in the C code, perform the following from the development environment before/during debug. From the menu bar, Debug->Exceptions to bring up the exception handling dialog. Change the trapping of access violation from Stop in not handled to Stop always. This will allow the line of code causing the exception to be identified.

Caveats/suggestions


Note: If compiling and the following error message appears:

LINK : fatal error LNK1168: cannot open MyFunction.dll for writing

It’s because Matlab is still running after having invoked the DLL. To fix, simple type at the Matlab command prompt clear functions, or exit Matlab altogether.
Another important note: McAffee virus scan 4.0.2 and above can cause the pre-link build step to hang. To resolve this, either temporarily disable the virus scanner, or under the McAffee System Scan properties, Select “Program Files Only” under the Detection tab. See http://support.microsoft.com/support/kb/articles/Q250/6/70.ASP
Any files opened within a mex file should also be closed; else a new file will be opened each time the function is called, which could result in an “out of files” error.
Static variables may be used with in the code, which persist between function calls. However, clear functions Matlab command will cause the static variables to disappear.
printf() statements may be used freely within the C code.
Do not use malloc() or free() functions. Use mxCalloc(), mxFree(), or related mex function instead.

Sample Program


/***************************************************************

* file: MyFunction.c - Sample MEX source file. *

* Finds the unique data values in an array. *

***************************************************************/

#include
#include "mex.h"
/***************************************************************

* function: UniqueValues() - Find all the unique values within *

* a data set. *

* INPUTS: *

* pDataIn - Pointer to double floating point array of data *

* to be processed. *

* N - The number of double values in pDatain. *

* pDataUnique - Pointer to where unique values are placed. *

* RETURNS: *

* Count of the number of unique values. *

* NOTES: *

***************************************************************/

int UniqueValues(double *pDataIn, int N, double *pDataUnique)

{

int Count = 0; /* Count of number of unique values */



int i; /* Iteration counter for input data */

int j; /* Iteration counter for searching list of unique data */

double Tolerance; /* How close values must be to be non-unique */

int Unique_Flag; /* Set until it's determined a value is a duplicate */


Tolerance = 0.0; /* Zero tolerance. Exercise for student: make this */

/* a parameter passed in from Matlab */

for (i=0; i

{

Unique_Flag = 1;



for (j=0; j

if (fabs(pDataIn[i] - pDataUnique[j]) <= Tolerance)

{

Unique_Flag = 0; /* This value already occured. */



break;

}

if (Unique_Flag)



{

/* New value found. Add to list of uniques. */

pDataUnique[Count] = pDataIn[i];

Count++;


}

}
return Count; /* Return number of unique values */

} /* end UniqueValues() */
/***************************************************************

* function: mexFunction() - Matlab interface function. *

* INPUTS: *

* nlhs - The number of output variables to be assigned by *

* the mex function. *

* plhs[] - Empty array of MATLAB matricies, of size nlhs. *

* This is to be filled in by this application. *

* nrhs - Number of input arguments to this mex funciton. *

* prhs[] - Array of MATLAB matricies from which input data *

* is taken. *

* RETURNS: *

* N/A *


* NOTES: *

* For this application (unique value finder): *

* nlhs is allowed to be only 0 or 1. Error otherwise. *

* nrhs must be exactly 1. Error otherwise. *

* Currently operates only on real valued data. *

***************************************************************/

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])

{

/* Define some shortcuts to the input and output data matrix pointers. */



#define DATA_IN prhs[0]

#define DATA_OUT plhs[0]


/* Variable to hold pointer to the input and output data, within the matirx*/

double *pDataIn; /* Pointer to input data */

int nRow; /* Number of rows (M) in the input data matrix */

int nCol; /* Number of columns (N) in the input data matrix */

int nElement; /* Total number of elements (N*M) */

double *pDataOut; /* Pointer to output data */

int Count; /* Number of elements output data is to contain */
/* Validate the nuber of input and output arguments */

if (nlhs > 1)

mexErrMsgTxt("Too many output arguments."); /* This terminates mex function. */

if (nrhs > 1)

mexErrMsgTxt("Too many input arguments."); /* This terminates mex function. */

if (nrhs < 1)

mexErrMsgTxt("Missing input argument."); /* This terminates mex function. */
/* Retrieve the pointer to the input data */

pDataIn = mxGetPr(DATA_IN);

nRow = mxGetM(DATA_IN);

nCol = mxGetN(DATA_IN);

nElement = nRow*nCol;
/* Create an output matrix necessary to hold all unique values. */

/* (assume for this purpose that all values are unique, and */

/* make it smaller later.) */

/* Make it multiple rows, single column. */

DATA_OUT = mxCreateDoubleMatrix(nElement, 1, mxREAL);

pDataOut = mxGetPr(DATA_OUT); /* Pointer to data space created */


/* Call the function which computes unique values */

Count = UniqueValues(pDataIn, nElement, pDataOut);


/* This tricky code changes the size of the output matrix in */

/* three steps. */

/* 1. Reallocate smaller portion of memory */

pDataOut = mxRealloc(pDataOut, Count * mxGetElementSize(DATA_OUT));

/* 2. Have the Matlab matrix point to the new memory location */

mxSetPr(DATA_OUT, pDataOut);

/* 3. Apply the new number of rows to the matrix */

mxSetM(DATA_OUT, Count); /* Change the number of rows */


return;
} /* end mexFunction() */




Verilənlər bazası müəlliflik hüququ ilə müdafiə olunur ©atelim.com 2016
rəhbərliyinə müraciət