mexampl2 calls the following MEX functions, and discusses their use in detail:
mexCallMATLAB mexEvalString mxGetPi mxFreeMatrix mxCreateString mxGetName.mexampl2 also calls the following MEX functions, which are described more fully in mexample, the first C MEX-files tutorial:
mexErrMsgTxt mxGetM mxGetN mxIsString mxIsSparse mxCreateFull mxGetPrIn addition, certain basic aspects of MATLAB Handle Graphics are briefly covered in this example.
------------------------------------------------------------
/* Include basic header files: */
#include <math.h> /* for sqrt, fabs, atan, etc. */
#include <stdio.h> /* for NULL */
#include <mex.h>
/* First, create two utility functions. These functions accept two
arrays of doubles (one representing the real part of a vector
and the other representing the imaginary part of the vector) and
return the magnitude and phase of these arrays. The output data
is stored in a third input array (whose memory has been
preallocated), while a fourth input argument represents the
length of the arrays. */
#ifdef __STDC__
void magnitude(
double *realData, /* real part of the input vector */
double *imagData, /* imaginary part of the input vector */
double *magData, /* magnitude of the input vector (return
argument)
*/
int vectorSize /* size of the input vector */
)
#else
magnitude(realData,imagData,magData,vectorSize)
double *realData; /* real part of the input vector */
double *imagData; /* imaginary part of the input vector */
double *magData; /* magnitude of the input vector (return
argument)
*/
int vectorSize; /* size of the input vector */
#endif
{
int element; /* loop counter to cycle through elements of the
input vector */
/* if imagData is not NULL, loop through each element of the input
vector. For each element, store in magData the square root of
the sum of the squares of the real and imaginary parts. */
if (imagData != NULL)
for (element=0;element<vectorSize;element++)
magData[element] = sqrt(realData[element]*realData[element]+
imagData[element]*imagData[element]);
else /* otherwise imaginary part is zero, take a
short cut: */
for (element=0;element<vectorSize;element++)
magData[element] = fabs(realData[element]);
} /* END magnitude() */
#define PI 3.1415926535897934440892098500626
#ifdef __STDC__
void phase(
double *realData, /* real part of the input vector */
double *imagData, /* imaginary part of the input vector */
double *phaseData, /* phase of the input vector (return argument)
*/
int vectorSize /* size of the input vector */
)
#else
phase(realData,imagData,phaseData,vectorSize)
double *realData; /* real part of the input vector */
double *imagData; /* imaginary part of the input vector */
double *phaseData; /* phase of the input vector (return argument)
*/
int vectorSize; /* size of the input vector */
#endif
{
int element; /* loop counter to cycle through elements of the
input vector */
/* if imagData is not NULL, loop through each element of the input
vector. For each element, store in phaseData the inverse
tangent of the imaginary part of the vector divided by the real
part of the vector. */
if (imagData != NULL)
for (element=0;element<vectorSize;element++)
phaseData[element] = atan(imagData[element]/realData[element]);
else /* otherwise imaginary part is zero, take a
short cut: */
for (element=0;element<vectorSize;element++)
phaseData[element] = (realData[element] > 0 ? 0 : PI);
} /* END phase() */
/* Now that the utility functions are defined, we can work on
mexFunction itself. But first, some definitions: */
#define VECTOR_IN prhs[0]
#define SCALAR_OUT plhs[0]
#ifdef __STDC__
void mexFunction(
int nlhs,
Matrix *plhs[],
int nrhs,
Matrix *prhs[]
)
#else
mexFunction(nlhs, plhs, nrhs, prhs)
int nlhs, nrhs;
Matrix *plhs[], *prhs[];
#endif
{
/* We will be making several calls to the function mexCallMATLAB.
Two of that function's inputs are arrays of Matrix pointers.
The next two variables will be used when we make these calls.
None of the mexCallMATLAB calls use more than five input
variables or result in more than 1 output variable, so
MCM_inputs is declared as a 5-element array, and MCM_outputs is
declared as a 1 element array. Optionally, if the maximum
number of input or output variables were not known ahead of
time, we could declare MCM_inputs and MCM_outputs to be of type
Matrix **, and then allocate memory for the array using
mxCalloc. */
Matrix * MCM_inputs[5]; /* Matrix pointer array for mexCallMATLAB
function */
Matrix * MCM_outputs[1];/* Matrix pointer array for mexCallMATLAB
function */
Matrix * figure_handle; /* handle to figure that mexampl2 creates */
int size_VECTOR_IN;/* number of elements in VECTOR_IN */
/* Step 1: Input checking.
Step 1a: Check nlhs. Should be 0 or 1. */
if (nlhs > 1)
mexErrMsgTxt("mexampl2 only returns up to 1 argument.");
/* Step 1b: Check nrhs. Should be 1. */
if (nrhs != 1)
mexErrMsgTxt("Requires 1 input argument.");
/* Step 1c: check VECTOR_IN (prhs[0]). Should be one-dimensional,
full, and numeric. Should not be sparse or a string. */
if ( ((mxGetM(VECTOR_IN) != 1) && (mxGetN(VECTOR_IN) != 1)) ||
mxIsString(VECTOR_IN) || mxIsSparse(VECTOR_IN) )
mexErrMsgTxt("Input argument should be Nx1 or 1xN, \
full, and numeric.");
/* For ease later on, we store the size of VECTOR_IN in the
variable size_VECTOR_IN. */
size_VECTOR_IN = mxGetM(VECTOR_IN) * mxGetN(VECTOR_IN);
/* Step 2: create figure and plot the plots.
Step 2a: create the figure. In MATLAB, the figure is created
with the figure command. To do it here, we will use
mexCallMATLAB to call the figure function. The arguments to
mexCallMATLAB are similar to those for mexFunction itself.
There is nlhs (the number of output arguments we are
requesting), plhs (an array of pointers to the output
arguments), nrhs (the number of input arguments), and
prhs (an array of pointers to the input arguments). In
addition, there is a string which contains the name of the
function we are going to call (in this case, figure). The
mexCallMATLAB call below, then, mimics the MATLAB command
"figure_handle = figure;". Note that in this case there are
zero inputs to figure, so MCM_inputs does not need to be
initialized. */
mexCallMATLAB(1,MCM_outputs,0,MCM_inputs,"figure");
/* Save result (the figure handle) to SCALAR_OUT. Since
mexCallMATLAB reallocates memory for its second argument,
plhs, each time it is called, we don't need to worry about a
future mexCallMATLAB call writing over figure_handle.*/
figure_handle = MCM_outputs[0];
/* Step 2b: Create each subplot, title it, and plot the
corresponding data. This consists of calling mexEvalString to
call subplot and title, and mexCallMATLAB to call plot. We
repeat this twice to plot the magnitude and phase.
mexEvalString is a simple function which passes its one input, a
string, to MATLAB for parsing. Thus it is similar to the eval
command in MATLAB. */
mexEvalString("subplot(2,1,1);"); /* causes MATLAB to execute
subplot(2,1,1); */
/* Create a matrix to pass to plot as the data to be plotted. */
MCM_inputs[0] = mxCreateFull(size_VECTOR_IN,1,REAL);
/* Load this matrix with the magnitude of VECTOR_IN: */
magnitude(mxGetPr(VECTOR_IN),mxGetPi(VECTOR_IN),
mxGetPr(MCM_inputs[0]),size_VECTOR_IN);
/* Call mexCallMATLAB: */
mexCallMATLAB(0,MCM_outputs,1,MCM_inputs,"plot");
/* Title the plot: */
mexEvalString("title('Magnitude');"); /* Causes MATLAB to execute
title('Magnitude'); */
/* Do it again for imaginary part: First, the subplot command: */
mexEvalString("subplot(2,1,2);");
/* Load the matrix with the phase of VECTOR_IN: */
phase(mxGetPr(VECTOR_IN),mxGetPi(VECTOR_IN),
mxGetPr(MCM_inputs[0]),size_VECTOR_IN);
/* Call mexCallMATLAB: */
mexCallMATLAB(0,MCM_outputs,1,MCM_inputs,"plot");
/* Title the plot: */
mexEvalString("title('Phase');");
/* Free the matrix pointed to by MCM_inputs[0]. */
mxFreeMatrix(MCM_inputs[0]);
/* For our second to last task, let's make the title of the figure
be the name of the variable being plotted. To do this, we need
to set the figure's 'NumberTitle' property to 'off' and its
'Name' property to the name of the variable. We do this with
another call to mexCallMATLAB, which call the MATLAB set
command. To create the MATLAB strings 'NumberTitle', 'off', and
'Name', we use the function mxCreateString. This function
accepts a string input and returns a MATLAB string Matrix
containing that string. Note that since mxGetName returns a
string with the name of VECTOR_IN, we can pass its output
directly to mxCreateString to create a MATLAB string containing
the name of VECTOR_IN. */
MCM_inputs[0] = figure_handle;
MCM_inputs[1] = mxCreateString("NumberTitle");
MCM_inputs[2] = mxCreateString("off");
MCM_inputs[3] = mxCreateString("Name");
MCM_inputs[4] = mxCreateString(mxGetName(VECTOR_IN));
mexCallMATLAB(0,MCM_outputs,5,MCM_inputs,"set");
/* The above mexCallMATLAB call mimics the MATLAB command
set(figure_handle,'NumberTitle','off', ...
'Name',<name of VECTOR_IN>);
Note, however, that using MEX-files allows users access to the
name of the input variable, something which no ordinary M-file
could do!
*/
/* Finally, we need to determine what the value of SCALAR_OUT
should be. This depends on nlhs. If nlhs equals 1, then the
user requested we return the figure handle, and so SCALAR_OUT
should be set to figure_handle. If nlhs equals 0, no such
request was made, and SCALAR_OUT should be NULL. */
if (nlhs)
SCALAR_OUT = figure_handle;
else
SCALAR_OUT = NULL;
} /* END mexFunction() */
(c) Copyright 1994 by The MathWorks, Inc.