How can I develop and build S-Functions for Simulink that Incorporate Ada Code?
MATLAB: Developing and Building S-Functions for Simulink® that Incorporate Ada Code
Related Solutions
We officially support C++ MEX-file S-functions as of Simulink 4.0 (R12).
To view an example of how to do this, please type:
sfundemos
at the MATLAB Command Prompt. This will open sfundemos.mdl. This demo that ships with SIMULINK provides examples of how to write different types of S-Functions and includes a C++ example.
You can also take a look at chapter 4 of the "Writing S-function" manual which has a good description on writing C++ MEX-file S-functions.
When writing the S-function, declare the MEX Function as extern "C". The rest of the code that you write can all be in C++. For example:
extern "C" { void mexFunction( int nlhs_, mxArray *plhs_[], int nrhs_, const mxArray *prhs_[]) { /* Body can use all C++ language features and file can be compiled with a C++ compiler */ } }
Below is the 'Timestwo' example written as a C++ file. You can compile the file using the MEX command. Note that if you are using the Watcom compiler, you need to add the -DNO_BUILT_IN_SUPPORT_FOR_BOOL flag to your COMPFLAGS option in your options file.
If you are using MSVC 5.0, you do not need to add this flag. The C compiler will automatically know to compile it as C++ code using the mex command.
/** TIMESTWO An example C-file S-function for multiplying an input by 2* * y = 2*x* * See sfuntmpl.c for a general S-function template.** See also VSFUNC, DSFUNC, SFUNTMPL.* * Copyright (c) 1990-96 by MathWorks, Inc.* All Rights Reserved* $Revision: 1.1 $*/ #ifdef __cplusplus extern "C" { #endif #define S_FUNCTION_NAME timestwo_level1_cpp /* The following three lines are necessary for the WATCOM compiler* only. You need to remove these lines for the MSVC compiler.*/ #ifndef COMPILER_SUPPORTS_BOOL typedef int bool; #endif #include "simstruc.h" /** mdlInitializeSizes - initialize the sizes array*/ static void mdlInitializeSizes(SimStruct *S) { ssSetNumContStates( S, 0); /* number of continuous states */ ssSetNumDiscStates( S, 0); /* number of discrete states */ ssSetNumInputs( S, DYNAMICALLY_SIZED); /* number of inputs */ ssSetNumOutputs( S, DYNAMICALLY_SIZED); /* number of outputs */ ssSetDirectFeedThrough(S, 1); /* direct feedthrough flag */ ssSetNumSampleTimes( S, 1); /* number of sample times */ ssSetNumSFcnParams( S, 0); /* number of input arguments */ ssSetNumRWork( S, 0); /* number of real work vector elements */ ssSetNumIWork( S, 0); /* number of integer work vector elements */ ssSetNumPWork( S, 0); /* number of pointer work vector elements */ } /** mdlInitializeSampleTimes - initialize the sample times array*/ static void mdlInitializeSampleTimes(SimStruct *S) { ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME); ssSetOffsetTime(S, 0, 0.0); } /** mdlInitializeConditions - initialize the states*/ static void mdlInitializeConditions(double *x0, SimStruct *S) { } /** mdlOutputs - compute the outputs*/ static void mdlOutputs(double *y, double *x, double *u, SimStruct *S, int tid) { class mul2 { double *u; double *y; int width; public: mul2(double *u_i, double *y_i, int width_i) { u = u_i; y = y_i; width = width_i; } void output(void) { for (int i=0;i<width;i++) { *y++=2.0*(*u++); } } }; class mul2 m(u,y,ssGetNumOutputs(S)); m.output(); } /** mdlUpdate - perform action at major integration time step*/ static void mdlUpdate(double *x, double *u, SimStruct *S, int tid) { } /** mdlDerivatives - compute the derivatives*/ static void mdlDerivatives(double *dx, double *x, double *u, SimStruct *S, int tid) { } /** mdlTerminate - called when the simulation is terminated.*/ static void mdlTerminate(SimStruct *S) { } #ifdefMATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */ #include "simulink.c" /* MEX-file interface mechanism */ #else #include "cg_sfun.h" /* Code generation registration function */ #endif #ifdef __cplusplus } #endif
Here is an example showing how to write a C-MEX S-function with dynamically sized input ports that accepts 1-D (vector) signals with different widths in Simulink 6.2 (R14SP2).
In Level 2 S-functions you need to use the two new methods: mdlSetInputPortWidth and mdlSetOutputPortWidth. This is described in the S-function section of the Using Simulink User's Guide.
If you open up the attached S-function source file, you will notice the following lines after mdlInitializeSizes:
#if defined(MATLAB_MEX_FILE)# define MDL_SET_INPUT_PORT_WIDTH static void mdlSetInputPortWidth(SimStruct *S, int_T port, int_T inputPortWidth) { ssSetInputPortWidth(S,port,inputPortWidth); }# define MDL_SET_OUTPUT_PORT_WIDTH static void mdlSetOutputPortWidth(SimStruct *S, int_T port,int_T outputPortWidth) { ssSetOutputPortWidth(S,port,outputPortWidth); }#endif
These methods are called with the candidate widths for dynamically sized ports. If the proposed widths are acceptable, the methods proceed to set the actual ports widths using ssSetInputPortWidth and ssSetOutputPortWidth.
Related Question
- Generation of an S-function block in simulink by integrating legacy C-code through the legacy code tool
- How to build an ADA S-Function in a 64 bit MATLAB
- S-function for static library
- Do I get a Port Width mismatch error in the CMEX S-function when using dynamically_sized for either the inputs or outputs
- How to generate an S-function that calls a C++ static library with other library dependencies
Best Answer
Section 1: IntroductionThis document describes how to invoke algorithms written in Ada within Simulink 7.5 (R2010a) and later via the creation and compilation of S-Functions. Though the Ada S-Function API is now deprecated, the extensive C Mex S-Function API for interfacing external tools and code to Simulink can be used to interface to Ada code. Files and examples are provided to facilitate this procedure. The document will be most useful to those familiar with Simulink software, S-Functions, the Ada language, and the GNAT family of Ada compilers.\n\n\n\n