Integrate C Functions Using Legacy Code Tool
Overview
You can integrate existing C (or C++) functions, such as device drivers, lookup tables, and general functions and interfaces, into Simulink® models by using the Legacy Code Tool. Using specifications that you supply as MATLAB® code, the tool transforms existing functions into C MEX S-functions that you can include in Simulink models. If you use Simulink Coder™ to generate code, Legacy Code Tool can insert an appropriate call to your C function into the generated code. For details, see Import Calls to External Code into Generated Code with Legacy Code Tool (Simulink Coder).
In comparison to using the S-Function Builder or writing an S-function, Legacy Code Tool is easier to use and generates optimized code (does not generate wrapper code) often required by embedded systems. However, consider alternative approaches for a hybrid system, such as a system that includes a plant and controller, or a system component written in a language other than C or C++. Alternative approaches are more flexible in that they support more features and programming languages.
To interact with the Legacy Code Tool, you
Use a Legacy Code Tool data structure to specify
A name for the S-function
Specifications for the existing C functions
Files and paths required for compilation
Options for the generated S-function
Use the
legacy_code
function toInitialize the Legacy Code Tool data structure for a given C function
Generate an S-function for use during simulation
Compile and link the generated S-function into a dynamically loadable executable
Generate a masked S-function block for calling the generated S-function
Generate a TLC block file and, if necessary, an
sFunction
_makecfg.m
orrtwmakecfg.m
file for code generation (Simulink Coder product license required)
Note
Before you can use legacy_code
, ensure that a C compiler is set
up for your MATLAB installation.
The following diagram illustrates a general procedure for using the Legacy Code Tool. Integrate C Functions into Simulink Models with Legacy Code Tool provides an example that uses the Legacy Code Tool to transform an existing C function into a C MEX S-function.
If you have a Simulink Coder product license, see Import Calls to External Code into Generated Code with Legacy Code Tool (Simulink Coder) for information on using the Legacy Code Tool for code generation.
Integrate C Functions into Simulink Models with Legacy Code Tool
This example demonstrates how to integrate an existing C function into a Simulink model using Legacy Code Tool.
Suppose that you have a C function that outputs the value of its floating-point input
multiplied by two. The function is defined in a source file named
doubleIt.c
, and its declaration exists in a header file named
doubleIt.h
.
Initialize a MATLAB struct
def
with fields that represent Legacy Code Tool properties using thelegacy_code
function.def = legacy_code('initialize')
The Legacy Code Tool data structure named
def
displays its fields in the MATLAB command window as shown here:def = SFunctionName: '' InitializeConditionsFcnSpec: '' OutputFcnSpec: '' StartFcnSpec: '' TerminateFcnSpec: '' HeaderFiles: {} SourceFiles: {} HostLibFiles: {} TargetLibFiles: {} IncPaths: {} SrcPaths: {} LibPaths: {} SampleTime: 'inherited' Options: [1x1 struct]
Specify appropriate values for fields in the Legacy Code Tool data structure to identify properties of the existing C function. For example, specify the C function source and header filenames by entering the following commands at the MATLAB command prompt:
def.SourceFiles = {'doubleIt.c'}; def.HeaderFiles = {'doubleIt.h'};
You must also specify information about the S-function that the Legacy Code Tool produces from the C code. For example, specify a name for the S-function and its output function declaration by entering:
def.SFunctionName = 'ex_sfun_doubleit'; def.OutputFcnSpec = 'double y1 = doubleIt(double u1)';
For information about the various data structure fields, see the
legacy_code
reference page.Generate an S-function source file from the existing C function by using the
legacy_code
function. At the MATLAB command prompt, type:legacy_code('sfcn_cmex_generate', def);
The Legacy Code Tool uses the information specified in
def
to create the S-function source file namedex_sfun_doubleit.c
in the current MATLAB folder.Compile and link the S-function source file into a dynamically loadable executable for Simulink using the
legacy_code
function. At the MATLAB command prompt, type:legacy_code('compile', def);
The following messages appear in the MATLAB command window:
### Start Compiling ex_sfun_doubleit mex('ex_sfun_doubleit.c', 'd:\work\lct_demos\doubleIt.c', '-Id:\work\lct\lct_demos') ### Finish Compiling ex_sfun_doubleit ### Exit
On a 32-bit Microsoft® Windows® system, the resulting S-function executable is named
ex_sfun_doubleit.mexw32
.Insert a masked S-Function block into a Simulink model.
legacy_code('slblock_generate', def);
The Legacy Code Tool configures the block to use the C MEX S-function created in the previous step. Also, the tool masks the block such that it displays the value of its
OutputFcnSpec
property (see the description of thelegacy_code
function).Add a Sine Wave block of amplitude 1 to the input of the C-MEX S-function block and a Scope block to the output.
Run the simulation. The C-MEX S-Function block returns the value of its floating-point input multiplied by two. It behaves like the C function
doubleIt
.
Integrate C Function Whose Arguments Are Pointers to Structures
This example shows how to use the Legacy Code Tool to integrate a C function whose arguments are pointers to structures.
In Simulink®, create a Simulink.Bus
object to represent a structure type. Use bus signals in a model to represent structured signals and states. Create MATLAB structures in a workspace or in a block parameter dialog box to represent parameter structures.
For information about buses, see Composite Interface Guidelines. For information about parameter structures, see Organize Related Block Parameter Definitions in Structures. To create bus objects, see Create Simulink Bus Objects.
Explore External Code
Copy this custom source code into a file named ex_mySrc_LCT.c
in your current folder.
<include>ex_mySrc_LCT.c</include>
The arguments of the function myFcn
are pointers to structures. The function accepts an input signal argument, a parameter argument, and an output signal argument.
Copy this custom header code into a file named ex_myTypes_LCT.h
in your current folder.
<include>ex_myTypes_LCT.h</include>
The file defines the signal and parameter structure types that myFcn
uses.
Create Bus Objects to Represent Structure Types in Simulink
At the command prompt, use the function Simulink.importExternalCTypes
to generate bus objects in the base workspace.
Simulink.importExternalCTypes('ex_myTypes_LCT.h');
The bus objects correspond to the struct
types that ex_myTypes_LCT.h
defines.
Create Block to Execute External Code
Create a structure variable, def
, to store the specifications for an S-function that calls the external code. Use the function legacy_code
to create the structure and set default values.
def = legacy_code('initialize');
Set the name of the S-function to sfun_ex_mySrc_LCT
.
def.SFunctionName = 'sfun_ex_mySrc_LCT';
Identify the external source and header files by their file names.
def.SourceFiles = {'ex_mySrc_LCT.c'}; def.HeaderFiles = {'ex_myTypes_LCT.h'};
Specify the prototype of the output function, which the model calls every simulation step, by copying the prototype of the external function myFcn
. Set the names of the arguments to u1
, p1
, and y1
to represent the input argument, the parameter argument, and the output argument. Use the syntax [1]
to specify that each argument is a pointer.
def.OutputFcnSpec = ['void myFcn(sigStructType u1[1], ',... 'paramStructType p1[1], sigStructType y1[1])'];
Use the function legacy_code
to create the S-function and the corresponding C MEX executable from the specification, def
. Specify the option 'generate_for_sim'
to prepare the S-function for normal and accelerated simulations.
legacy_code('generate_for_sim',def);
### Start Compiling sfun_ex_mySrc_LCT mex('-I/tmp/Bdoc23b_2361005_2341001/tpf683a620/simulink-ex12763634', '-c', '-outdir', '/tmp/Bdoc23b_2361005_2341001/tpbf01e976_364e_4883_b480_9468cece2d1e', '/tmp/Bdoc23b_2361005_2341001/tpf683a620/simulink-ex12763634/ex_mySrc_LCT.c') Building with 'gcc'. MEX completed successfully. mex('sfun_ex_mySrc_LCT.c', '-I/tmp/Bdoc23b_2361005_2341001/tpf683a620/simulink-ex12763634', '/tmp/Bdoc23b_2361005_2341001/tpbf01e976_364e_4883_b480_9468cece2d1e/ex_mySrc_LCT.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_ex_mySrc_LCT ### Exit
Create a masked S-Function block that calls the S-function during simulation.
legacy_code('slblock_generate', def);
The block appears in a new model.
To use the S-Function block in your model, create a bus signal of type sigStructType
to use as the block input. The block output is also a bus signal. The block mask accepts a parameter, P1. To set the value of the parameter, use a MATLAB structure whose fields match those of the structure type paramStructType
.
Verify Execution of External Code
Create a harness model that verifies the execution of the external code during simulation.
For an example, view the model ex_lct_struct
.
open_system('ex_lct_struct')
In the Constant block dialog box, the Constant value parameter is set to a structure whose fields match those of the structure type sigStructType
. On the Signal Attributes tab, Output data type is set to the bus object sigStructType
.
The S-Function block calls the S-function sfun_ex_mySrc_LCT
that you created. The output of the block enters a Bus Selector block, which extracts the signal elements sig1
and sig2
.
The S-Function block accepts a parameter through the mask dialog box. Create a MATLAB structure structParam
to use as the value of the parameter.
structParam = struct; structParam.param1 = 15; structParam.param2 = 20; structParam.param3 = 5;
Optionally, use a Simulink.Parameter
object to contain the structure. If you use a parameter object, you can set the data type of the structure by using the bus object paramStructType
.
structParam = Simulink.Parameter(structParam);
structParam.DataType = 'Bus: paramStructType';
In the mask dialog box, set P1 to structParam
.
set_param('ex_lct_struct/sfun_ex_mySrc_LCT','SParameter1','structParam')
Simulate the model. The Scope blocks show that the S-Function block calls the external function myFcn
.
open_system('ex_lct_struct/Scope') open_system('ex_lct_struct/Scope1') sim('ex_lct_struct') %
Registering Legacy Code Tool Data Structures
The first step to using the Legacy Code Tool is to register one or more MATLAB structures with fields that represent properties of the existing C code and the S-function being generated. The registration process is flexible. You can choose to set up resources and initiate registration in a variety of ways, including
Placing all required header and source files in the current working folder or in a hierarchical folder structure
Generating and placing one or more S-functions in the current working folder
Having one or more registration files in the same folder
To register a Legacy Code Tool data structure:
Use the
legacy_code
function, specifying'initialize'
as the first argument.lct_spec = legacy_code('initialize')
The Legacy Code Tool data structure named
lct_spec
displays its fields in the MATLAB command window as shown below:lct_spec = SFunctionName: '' InitializeConditionsFcnSpec: '' OutputFcnSpec: '' StartFcnSpec: '' TerminateFcnSpec: '' HeaderFiles: {} SourceFiles: {} HostLibFiles: {} TargetLibFiles: {} IncPaths: {} SrcPaths: {} LibPaths: {} SampleTime: 'inherited' Options: [1x1 struct]
Define values for the data structure fields (properties) that apply to your existing C function and the S-function you intend to generate. Minimally, you must specify
Source and header files for the existing C function (
SourceFiles
andHeaderFiles
)A name for the S-function (
SFunctionName
)At least one function specification for the S-function (
InitializeConditionsFcnSpec
,OutputFcnSpec
,StartFcnSpec
,TerminateFcnSpec
)
For a complete list and descriptions of the fields in the structure, see the
legacy_code
function reference page.
If you define fields that specify compilation resources and you specify relative paths, the Legacy Code Tool searches for the resources relative to the following directories, in the following order:
Current working folder
C-MEX S-function folder, if different than the current working folder
Directories you specify
IncPaths
for header filesSrcPaths
for source filesLibPaths
for target and host libraries
Directories on the MATLAB search path, excluding toolbox directories
Declaring Legacy Code Tool Function Specifications
The InitializeConditionsFcnSpec
, OutputFcnSpec
, StartFcnSpec
, and TerminateFcnSpec
fields defined in the Legacy Code Tool data structure (see the description of
the legacy_code
function) require character
vector values that adhere to a specific syntax format. The required syntax format enables
the Legacy Code Tool to map the return value and arguments of an existing C function to the
return value, inputs, outputs, parameters, and work vectors of the S-function that the tool
generates.
General syntax
return-spec = function-name(argument-spec)
For example, the following character vector specifies a function named
doubleIt
with return specification double y1
and
input argument specification double u1
.
def.OutputFcnSpec = 'double y1 = doubleIt(double u1)';
For more detail on declaring function specifications, see
Return Specification
The return specification defines the data type and variable name for the return value of the existing C function.
return-type return-variable
| A data type listed in Supported Data Types. |
| Token of the form y1 , y2 ,
... , y n, where
n is the total number of output arguments. |
If the function does not return a value, you can omit the return specification or
specify it as void
.
The following table shows valid function specification syntax for an integer return value. Use the table to identify the syntax you should use for your C function prototype.
Return Type | C Function Prototype | Legacy Code Tool Function Specification |
---|---|---|
No return value | void myfunction(...) | void myfunction(...) |
Scalar value | int = myfunction(...) | int16 y1 = myfunction(...) |
Function Name
The function name that you specify must be the same as your existing C function name.
For example, consider the following C function prototype:
float doubleIt(float inVal);
In this case, the function name in the Legacy Code Tool function specification must be
doubleIt
.
You should not specify the name of a C macro. If you must, set the field
Options.isMacro
to true
in case expression folding
is enabled.
Argument Specification
The argument specification defines one or more data type and token pairs that represent the input, output, parameter, and work vector arguments of the existing C function. The function input and output arguments map to block input and output ports and parameters map to workspace parameters.
argument-type argument-token
| A data type listed in Supported Data Types. |
| Token of one of the following forms:
|
If the function has no arguments, you can omit the argument specification or specify
it as void
.
Consider the following C function prototype:
float powerIt(float inVal, int exponent);
To generate an S-function that calls the preceding function at each time step, set the
Legacy Code Tool data structure field OutputFcnSpec
to the
following:
'single y1 = powerIt(single u1, int16 p1)'
Using this function specification, the Legacy Code Tool maps the following information.
Return Value or Argument | of C Type | To Token | of Data Type |
---|---|---|---|
Return value | float | y1 | single |
inVal | float | u1 | single |
exponent | int | p1 | int16 |
If your function requires a Simulink S-function block with multiple input and output
ports, map function arguments to input ports using a uniquely numbered
u
token. For output ports, use a uniquely numbered
y
token. These tokens are described in the preceding argument
specification table. For example, consider the following C function prototype:
void myfunc(double *y2, double u2, double u3, double u1, double *y1);
An OutputFcnSpec
character vector mapping the arguments to input
and output ports looks similar to the following:
'void myfunc(double y2[1],double u2,double u3,double u1,double y1[1])'
The resulting S-function block includes three input ports and two output ports. The
first input maps to function argument u1
, the second input to
u2
, and the third input to u3
. For the output
ports, the function argument y1[1]
maps to the first output, and
argument y2[1]
maps to the second output. For another example of
mapping a function prototype to multiple input and output ports, see Using Buses with Legacy Functions Having Structure Arguments.
The following table shows valid function specification syntax for arguments of type integer. Use the table to identify and then adapt the syntax you should use for your C function prototype.
Argument Type | C Function Prototype | Legacy Code Tool Function Specification |
---|---|---|
Input Arguments | ||
No arguments | function(void) | function(void) |
Scalar pass by value | function(int in1) | function(int16 u1) |
Scalar pass by pointer | function(int *in1) | function(int16 u1[1]) |
Fixed vector | function(int in1[10])
orfunction(int *in1) | function(int16 u1[10]) |
Variable vector | function(int in1[])
orfunction(int *in1) | function(int16 u1[]) |
Fixed matrix | function(int in1[15])
orfunction(int in1[])
orfunction(int *in1) | function(int16 u1[3][5]) |
Variable matrix | function(int in1[])
orfunction(int *in1) | function(int16 u1[][]) |
Output Arguments | ||
Scalar pointer | function(int *y1) | function(int16 y1[1]) |
Fixed vector | function(int y1[10])
orfunction(int *y1) | function(int16 y1[10]) |
Fixed matrix | function(int y1[15])
orfunction(int y1[])
orfunction(int *y1) | function(int16 y1[3][5]) |
Parameter Arguments | ||
Scalar pass by value | function(int p1) | function(int16 p1) |
Scalar pass by pointer | function(int *p1) | function(int16 p1[1]) |
Fixed vector | function(int p1[10])
orfunction(int *p1) | function(int16 p1[10]) |
Variable vector | function(int p1[])
orfunction(int *p1) | function(int16 p1[]) |
Fixed matrix | function(int p1[15])
orfunction(int p1[])
orfunction(int *p1) | function(int16 p1[3][5]) |
Variable matrix | function(int p1[])
orfunction(int *p1) | function(int16 p1[][]) |
Work Vector Arguments | ||
Scalar passed by value | function(int work1) | function(int16 work1) |
Scalar pointer | function(int
*work1) function(void
*work1) function(void
**work1) | function(int16 work1[1]) void
function(void *work1) void function(void
**work1) |
Fixed vector | function(int work1[10])
orfunction(int *work1) | function(int16 work1[10]) |
Fixed matrix | function(int work1[15])
orfunction(int work1[])
orfunction(int *work1) | function(int16 work1[3][5]) |
Supported Data Types
Data Type | Supported for Input and Output? | Supported for Parameters? | Supported for Work Vectors? |
---|---|---|---|
Data Types Supported by Simulink
(with the exception of string ) | Yes | Yes | Yes |
Simulink.Bus 1 | Yes | Yes | Yes |
Array of Simulink.Bus 2 | Yes | No | Yes |
Simulink.NumericType 3 | Yes | Yes | Yes |
Simulink.AliasType 1 | Yes | Yes | Yes |
enum 1 | Yes | Yes | Yes |
Fixed-point4 | Yes | Yes | Yes |
Fi objects | N/A | Yes | N/A |
Complex numbers5 | Yes | Yes | Yes |
1-D array | Yes | Yes | Yes |
2-D array6 | Yes | Yes | Yes |
n-D array7 | Yes | Yes | Yes |
void * | No | No | Yes |
void ** | No | No | Yes |
You must supply the header file that defines the structure of the bus, defines the
enum
type, or defines the data type with the same name as an alias. The structure of the bus declared in the header file must match the structure of the bus object (for example, the number and order of elements, data types and widths of elements, and so on). For an example, see Using Buses with Legacy Functions Having Structure Arguments.To generate data type objects and enumeration classes that correspond to custom data types that your C code defines, use the
Simulink.importExternalCTypes
function.A bus element can be complex, but only with Simulink built-in data types. Nesting of arrays to any level is also supported.
You must supply the header file that defines the data type only if the numeric data type is also an alias.
You must declare the data as a
Simulink.NumericType
object (unspecified scaling is not supported). For examples, see Fixed Point Signals in Legacy Functions and Fixed Point Parameters in Legacy Functions.Limited to use with Simulink built-in data types. To specify a complex data type, enclose the built-in data type within angle brackets (<>) and prepend the word
complex
(for example,complex<double>
). For an example, see Complex Signals in Legacy Function.The MATLAB, Simulink, and Simulink Coder products store multidimensional array data in column-major format as a vector. If your external function code is written for row-major data, use
convertNDArrayToRowMajor
S-function option inlegacy_code
.For a multidimensional signal, you can use the
size
function to determine the number of elements in the signal. For examples, see Lookup Tables Implemented in Legacy Functions and Multi-Dimensional Signals in Legacy Functions.
For more information, see Data Types Supported by Simulink.
Legacy Code Tool Function Specification Rules
Specifications for the legacy_code
must adhere to the following
rules:
If an argument is not scalar, you must pass the argument by reference.
The numbering of input, output, parameter, and work vector argument tokens must start at 1 and increase monotonically.
For a given Legacy Code Tool data structure, the data type and size of input, output, parameter, and work vector arguments must be the same across function specifications for
StartFcnSpec
,InitializeConditionsFcnSpec
,OutputFcnSpec
, andTerminateFcnSpec
.You can specify argument dimensions with expressions that use the following:
Functions:
numel
,size
Parameter values
Operators:
+
,-
,*
, and/
Integer and floating point literals
Parentheses for grouping sub-expressions
For example:
def.OutputFcnSpec= foo4(int8 p1[], int8 u1[], double y1[numel(u1)+2][numel(u1)+3], ... int32 (numel(p1)+numel(u1))*2+size(y1,2))';
Legacy C Function Rules
To integrate a C function using the Legacy Code Tool, the function must adhere to the following rules:
The function must not change the value of input arguments. If an input signal is a passed-by-reference argument to the function, the function must not modify the data pointed to by the argument.
The function's return value cannot be a pointer.
Function specifications you define for the
StartFcnSpec
,InitializeConditionsFcnSpec
, orTerminateFcnSpec
cannot access input or output arguments. ForStartFcnSpec
andInitializeConditionsFcnSpec
, you can access output ports if the S-Function optionoutputsConditionallyWritten
is set totrue
. With this option setting, the generated S-Function specifies that the memory associated with each output port cannot be overwritten and is global (SS_NOT_REUSABLE_AND_GLOBAL
).
Generating and Compiling the S-Functions
After you register a Legacy Code Tool data structure for an existing C function, use the
legacy_code
function as explained below to
generate, compile, and link the S-function.
Generate a C MEX S-function based on the information defined in the structure. Call
legacy_code
with'sfcn_cmex_generate'
as the first argument and the name of the data structure as the second argument.legacy_code('sfcn_cmex_generate', lct_spec);
Compile and link the S-function. This step assumes that a C compiler is set up for your MATLAB installation. Call
legacy_code
with'compile'
as the first argument and the name of the data structure as the second argument.legacy_code('compile', lct_spec);
Informational messages similar to the following appear in the MATLAB command window and a dynamically loadable executable results. On a 32-bit Windows system, the Simulink software names the file
ex_sfun_doubleit.mexw32
.### Start Compiling ex_sfun_doubleit mex ex_sfun_doubleit.c -Id:\work\lct\lct_demos ### Finish Compiling ex_sfun_doubleit ### Exit
As a convenience, you can generate, compile, and link the S-function in a single step by
calling legacy_code
with the character vector
'generate_for_sim'
. The function also generates a TLC file for
accelerated simulations, if the Options.useTlcWithAccel
field of the
Legacy Code Tool data structure is set to 1.
Once you have generated a dynamically loadable executable, you or others can use it in a model by adding an S-Function block that specifies the compiled S-function.
Generating a Masked S-Function Block for Calling a Generated S-Function
You have the option of using the Legacy Code Tool to generate a masked S-function block
(graphical representation) that is configured to call a generated C MEX S-function. To
generate such a block, call legacy_code
with
'slblock_generate'
as the first argument and the name of the Legacy Code Tool data structure as
the second argument.
legacy_code('slblock_generate', lct_spec);
The tool masks the block such that it displays the value of the
OutputFcnSpec
field. You can then add the block to a model manually.
If you prefer that the Legacy Code Tool add the block to a model automatically, specify the name of the model as a third argument. For example:
legacy_code('slblock_generate', lct_spec, 'myModel');
If the specified model (for example, myModel
) exists,
legacy_code
opens the model and adds the masked S-function block
described by the Legacy Code Tool data structure. If the model does not exist, the function
creates a new model with the specified name and adds the masked S-function block.
Forcing Simulink Accelerator Mode to Use S-Function TLC Inlining Code
If you are using Simulink Accelerator™ mode, you can generate and force the use of TLC inlining code for the S-function generated by the Legacy Code Tool. To do this:
Generate a TLC block file for the S-function by calling the
legacy_code
function with'sfcn_tlc_generate'
as the first argument and the name of the Legacy Code Tool data structure as the second argument.legacy_code('sfcn_tlc_generate', lct_spec);
Consider the example in Integrate C Functions into Simulink Models with Legacy Code Tool. To generate a TLC file for the model shown at the end of that example, enter the following command:
legacy_code('sfcn_tlc_generate', def);
Force Accelerator mode to use the TLC file by using the
ssSetOptions
SimStruct
function to set the S-function optionSS_OPTION_USE_TLC_WITH_ACCELERATOR
.
Calling Legacy C++ Functions
To call a legacy C++ function after initializing the Legacy Code Tool data structure,
assign the value 'C++' to the Options.language
field. For example,
def = legacy_code('initialize'); def.Options.language = 'C++';
To verify the new setting, enter
def.Options.language
Note
The Legacy Code Tool can interface with C++ functions, but not C++ objects. For a work around, see Legacy Code Tool Limitations in the Simulink documentation.
Handling Multiple Registration Files
You can have multiple registration files in the same folder and generate an S-function
for each file with a single call to legacy_code
. Likewise, you can use
a single call to legacy_code
in order to compile and link the
S-functions and another to generate corresponding TLC block files, if appropriate.
Consider the following example, where lct_register_1
,
lct_register_2
, and lct_register_3
each create and
initialize fields of a Legacy Code Tool structure.
defs1 = lct_register_1; defs2 = lct_register_2; defs3 = lct_register_3; defs = [defs1(:);defs2(:);defs3(:)];
You can then use the following sequence of calls to legacy_code
in
order to generate files based on the three registration files:
legacy_code('sfcn_cmex_generate', defs); legacy_code('compile', defs); legacy_code('sfcn_tlc_generate', defs);
Alternatively, you can process each registration file separately. For example:
defs1 = lct_register1; legacy_code('sfcn_cmex_generate', defs1); legacy_code('compile', defs1); legacy_code('sfcn_tlc_generate', defs1); . . . defs2 = lct_register2; legacy_code('sfcn_cmex_generate', defs2); legacy_code('compile', defs2); legacy_code('sfcn_tlc_generate', defs2); . . . defs3 = lct_register3; legacy_code('sfcn_cmex_generate', defs3); legacy_code('compile', defs3); legacy_code('sfcn_tlc_generate', defs3);
Deploying Generated S-Functions
You can deploy the S-functions that you generate with the Legacy Code Tool for use by others. To deploy an S-function for simulation use only, you need to share only the compiled dynamically loadable executable.
Legacy Code Tool Examples
For examples of the Legacy Code Tool, see Implement Algorithms Using Legacy Code Tool.
Legacy Code Tool Limitations
Legacy Code Tool
Generates C MEX S-functions for existing functions written in C or C++. The tool does not support transformation of MATLAB or Fortran functions.
Can interface with C++ functions, but not C++ objects. One way of working around this limitation is to use the S-Function Builder to generate the shell of an S-function and then call the legacy C++ code from the S-function's
mdlOutputs
callback function.Does not support simulating continuous or discrete states. This prevents you from using the
mdlUpdate
andmdlDerivatives
callback functions. If your application requires this support, see Using the S-Function Builder to Incorporate Legacy Code.Always sets the S-functions flag for direct feedthrough (
sizes.DirFeedthrough
) totrue
. Due to this setting and the preceding limitation, the generated S-function cannot break algebraic loops.Supports only the continuous, but fixed in minor time step, sample time and offset option.
Supports complex numbers, but only with Simulink built-in data types.
Does not support use of function pointers as the output of the legacy function being called.
Does not support the following S-function features:
Work vectors, other than general DWork vectors
Frame-based input and output signals
Port-based sample times
Multiple block-based sample times
Does not support use of the scope (::) operator for access of C++ class data and methods. For static methods, you can write simple preprocessor macros, similar to the following, to work around this:
#define CCommon_computeVectorDotProduct CCommon::computeVectorDotProduct
Can generate a terminate function when you have not specified one if the function specification includes a Simulink data type that has the property
HeaderFile
. For an export function model, this terminate function can make the generated S-function incompatible with code generation.