MATLAB Data in C S-Functions
MATLAB® data is represented as mxArrays
in C/C++ language. The
mxArray
structure typically contains type, dimension, data, data
type, sparsity, and the field and field numbers of the MATLAB array. In S-functions, Pass Dialog Parameters to S-Functions values evaluated in MATLAB are transferred into Simulink® as an mxArray
. See C Matrix API
for a list of functions.
S-functions read MATLAB data mainly for the following purposes:
Access block dialog parameters using
mxArrays
Pass arguments to or from a MATLAB Function using
mexCallMATLAB
mxArray
Manipulation
You can manipulate mxArrays
in S-functions using the standard
MATLAB API functions. In general, if your S-function is declared exception
free by passing the SS_OPTION_EXCEPTION_FREE_CODE
option to
ssSetOptions
(see Exception Free Code in Handle Errors in S-Functions), it should avoid MATLAB API functions that throw exceptions (i.e., long jump), such as
mxCreateDoubleMatrix
. Otherwise, the S-function can use any
of the listed functions.
Note
S-function parameters are read-only within the S-function algorithm. You can modify parameter values via the S-function block dialog or mask.
If you have Simulink
Coder™, it supports a subset of the mxArray
manipulation
functions when generating noninlined code for an S-function. For a list of supported
functions, see Write Noninlined S-Function (Simulink Coder).
Calls to the macro ssGetSFcnParam
return a pointer to an
mxArray
, which can be used with the
mxArray
manipulation functions. If your S-function contains
S-function parameters, use the mxArray
manipulation functions in
the mdlCheckParameters
method to check the S-function parameter
values. See the S-function sfun_runtime3.c
for an example
In this S-function, the following lines check that the first S-function parameter is a character array with a length greater than or equal to two.
if (!mxIsChar(ssGetSFcnParam(S, 0)) || (nu=mxGetNumberOfElements(ssGetSFcnParam(S, 0))) < 2) { ssSetErrorStatus(S,"1st parameter to S-function must be a " "string of at least 2 '+' and '-' characters"); return; }
mxArrays
Using 32-bit APIs
To write C/C++ programs that work with MATLAB
mxArray
data structure, use C matrix APIs. C matrix APIs support
32-bit and 64-bit indexing. By default, your S-functions are built using 32-bit
APIs. Check Upgrade MEX Files to Use 64-Bit API to see how to upgrade your existing MEX
files.
To check the use of 32-bit APIs, you can run the S-function upgrade advisor. In the Modeling tab, select Model Advisor > Upgrade Advisor.
If you build your code with -largeArrayDims
and your code
populates the ssParamRec
structure's dimension field with
mxArray
dimensions, starting R2018a, you can no longer cast
the return value of mxGetDimensions
to an int_T
pointer
because mxGetDimensions
now returns a
size_T
pointer on 64-bit platforms. As a workaround, create a
temporary copy of type int_T
and assign it to the
dims
field of ssParamRec
structure.
Replace: | With: |
---|---|
ssParamRec p; p.dims = (int_T *) mxGetDimensions(ssGetSFcnParam(S, 0)); // Set up other fields of p if (!ssSetRunTimeParamInfo(S, 0, &p)) { free(dims); return; } free(dims); // free memory allocated for dimensions |
ssParamRec p; const mxArray* mxPrm = ssGetSFcnParam(S, 0); const mwSize* mxDims = mxGetDimensions(mxPrm); const mwSize mxNumDims = mxGetNumberOfDimensions(mxPrm); mwSize idx; int_T * dims = malloc(sizeof(int)*mxNumDims); for (idx=0; idx < mxNumDims; idx++) { dims[idx] = mxDims[idx]; } p.dims = dims; // Set up other fields of p if (!ssSetRunTimeParamInfo(S, 0, &p)) { free(dims); return; } free(dims); // free memory allocated for dimensions |
mxArrays
Using Interleaved Complex Representation
Until MATLAB version 9.4 (R2018a), mxArrays
used separate
complex representation where the real and imaginary parts of a complex number were
stored separately. Starting version 9.4 (R2018a), MATLAB uses interleaved representation to store complex data, where the real
and imaginary parts of a complex numbers are stored together. For S-functions to
manipulate mxArrays
, there is no longer need to convert data from
separate to interleaved complex. See MATLAB Support for Interleaved Complex API in MEX Functions for more
information on how to update your code.
Note
To store complex data for input and output signals or DWorks, Simulink uses interleaved representation.
To automatically check your S-functions on potential interleaved complex data issues, in the Modeling tab, select Model Advisor > Upgrade Advisor. In the Upgrade Advisor window, select Check model for S-function upgrade issues.
The following code sample copies a parameter value from an
mxArray
to the output of the S-function. In this example, the
dimensions, data type, and the complexity of the parameter and the output argument
are ensured to be the same. For example, if the parameter is complex, the output
signal is complex. If the parameter is real, the output signal is real. For the
example below, the data type of both the parameter and the output is a double
(real_T
). Before R2018a, you could use
mxGetPr
and mxGetPr
to copy the real and
imaginary parts of a complex data separately. With interleaved complex
representation, you can use memcpy
, which is a single copy
instruction.
Replace: | With: |
---|---|
real_T *y = ssGetOutputPortRealSignal(S,0); boolean_T yIsComplex = ssGetOutputPortComplexSignal(S, 0) == COMPLEX_YES; int_T yWidth = ssGetOutputPortWidth(S,0); const real_T *pr = mxGetPr(ssGetSFcnParam(S, 0)); const real_T *pi = mxGetPi(ssGetSFcnParam(S, 0)); int i; for (i = 0; i < yWidth; i++) { int_T idx = (yIsComplex) ? 2*i : i; y[idx] = pr[idx]; if(yIsComplex){ y[idx+1] = pi[idx]; } } |
real_T *y = ssGetOutputPortRealSignal(S,0); boolean_T yIsComplex = ssGetOutputPortComplexSignal(S, 0) == COMPLEX_YES; int_T yWidth = ssGetOutputPortWidth(S,0); mxComplexDouble *pc; mxDouble *pr; if (yIsComplex) { pc = mxGetComplexDoubles(ssGetSFcnParam(S, 0)); memcpy(y, pc, yWidth*sizeof(mxComplexDouble)); } else { pr = mxGetDoubles(ssGetSFcnParam(S, 0)); memcpy(y, pr, yWidth*sizeof(mxDouble)); } |
sizeof(mxComplexDouble)=2*sizeof(mxDouble)=2*sizeof(real_T) |
See Also
S-Function | S-Function Builder