MATLAB Data in C S-Functions - MATLAB & Simulink (original) (raw)
MATLAB® data is represented as mxArrays
in C/C++ language. ThemxArray
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 tossSetOptions
(see Exception Free Code in Handle Errors in S-Functions), it should avoid MATLAB API functions that throw exceptions (i.e., long jump), such asmxCreateDoubleMatrix
. 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 box 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 anmxArray
, which can be used with themxArray
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](https://mdsite.deno.dev/matlab:sfunddg%5Fcb%5Fedit%28'sfun%5Fruntime3'%29;)
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 MATLABmxArray
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 > .
If you build your code with -largeArrayDims
and your code populates the ssParamRec
structure's dimension field withmxArray
dimensions, starting R2018a, you can no longer cast the return value of mxGetDimensions
to an int_T pointer
because mxGetDimensions
now returns asize_T
pointer on 64-bit platforms. As a workaround, create a temporary copy of type int_T
and assign it to thedims
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 > . In the Upgrade Advisor window, select Check model for S-function upgrade issues.
The following code sample copies a parameter value from anmxArray
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 usemxGetPr
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)); } a |
a sizeof(mxComplexDouble)=2*sizeof(mxDouble)=2*sizeof(real_T) |
See Also
S-Function | S-Function Builder