Legacy Code Tool Examples
You can use the Simulink® Legacy Code Tool to generate fully inlined C MEX S-functions for legacy or custom code. The S-functions are optimized for embedded components, such as device drivers and lookup tables, and they call existing C or C++ functions. These examples show how to use the Legacy Code Tool to integrate a variety of external functions.
Integrate External C Functions That Pass Input Arguments by Value Versus Address
This example shows how to use the Legacy Code Tool to integrate legacy C functions that pass their input arguments by value versus address.
With the Legacy Code Tool, you can:
Provide the legacy function specification.
Generate a C-MEX S-function that calls the legacy code during simulation.
Compile and build the generated S-function for simulation.
Generate a TLC block file and optional rtwmakecfg.m file that specifies how the generated code for a model calls the legacy code.
Provide the Legacy Function Specification
Legacy Code Tool functions take a specific data structure or array of structures as the argument. You can initialize the data structure by calling the function legacy_code() using 'initialize' as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The prototypes of the legacy functions being called in this example are:
FLT filterV1(const FLT signal, const FLT prevSignal, const FLT gain)
FLT filterV2(const FLT* signal, const FLT prevSignal, const FLT gain)
FLT is a typedef to float. The legacy source code is in the files: * ct_src/your_types.h * lct_src/myfilter.h * lct_src/filterV1.c * lct_src/filterV2.c
Note the difference in the OutputFcnSpec defined in the two structures; the first case specifies that the first input argument is passed by value, while the second case specifies pass by pointer.
defs = []; % sfun_filterV1 def = legacy_code('initialize'); def.SFunctionName = 'sfun_filterV1'; def.OutputFcnSpec = 'single y1 = filterV1(single u1, single u2, single p1)'; def.HeaderFiles = {'myfilter.h'}; def.SourceFiles = {'filterV1.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'}; defs = [defs; def]; % sfun_filterV2 def = legacy_code('initialize'); def.SFunctionName = 'sfun_filterV2'; def.OutputFcnSpec = 'single y1 = filterV2(single u1[1], single u2, single p1)'; def.HeaderFiles = {'myfilter.h'}; def.SourceFiles = {'filterV2.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'}; defs = [defs; def];
Generate S-Functions for Simulation
To generate C-MEX S-functions according to the description provided by the input argument 'defs', call the function legacy_code() again with the first input set to 'sfcn_cmex_generate'. The S-functions call the legacy functions in simulation. The source code for the S-functions is in the files: * sfun_filterV1.c * sfun_filterV2.c
legacy_code('sfcn_cmex_generate', defs);
Compile the Generated S-Functions for Simulation
After you generate the C-MEX S-function source files, to compile the S-functions for simulation with Simulink®, call the function legacy_code() again with the first input set to 'compile'.
legacy_code('compile', defs);
### Start Compiling sfun_filterV1 mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tpe57ef8cf_c398_4ba7_9643_496f7f44cbf7', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214/filterV1.c') Building with 'gcc'. MEX completed successfully. mex('sfun_filterV1.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214', '/tmp/Bdoc24b_2725827_4048235/tpe57ef8cf_c398_4ba7_9643_496f7f44cbf7/filterV1.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_filterV1 ### Exit ### Start Compiling sfun_filterV2 mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp3fc82331_1372_4705_9e82_c8bafee755a8', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214/filterV2.c') Building with 'gcc'. MEX completed successfully. mex('sfun_filterV2.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214', '/tmp/Bdoc24b_2725827_4048235/tp3fc82331_1372_4705_9e82_c8bafee755a8/filterV2.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_filterV2 ### Exit
Generate TLC Block Files for Code Generation
After you compile the S-functions and use them in simulation, you can call the function legacy_code() again with the first input set to 'sfcn_tlc_generate' to generate TLC block files. Block files specify how the generated code for a model calls the legacy code. If you do not generate TLC block files and you try to generate code for a model that includes the S-functions, code generation fails. The TLC block files for the S-functions are: * sfun_filterV1.tlc * sfun_filterV2.tlc
legacy_code('sfcn_tlc_generate', defs);
Generate an rtwmakecfg.m File for Code Generation
After you create the TLC block files, you can call the function legacy_code() again with the first input set to 'rtwmakecfg_generate' to generate an rtwmakecfg.m file to support code generation. If the required source and header files for the S-functions are not in the same folder as the S-functions, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m file.
legacy_code('rtwmakecfg_generate', defs);
Generate Masked S-Function Blocks for Calling the Generated S-Functions
After you compile the C-MEX S-function source, you can call the function legacy_code() again with the first input set to 'slblock_generate' to generate masked S-function blocks that call the S-functions. The software places the blocks in a new model. From there you can copy them to an existing model.
legacy_code('slblock_generate', defs);
Show the Generated Integration with Legacy Code
The model LctValueVersusAddress shows integration of the model with the legacy code. The subsystem TestFilter serves as a harness for the calls to the legacy C functions via the generate S-functions, with unit delays serving to store the previous output values.
open_system('LctValueVersusAddress') open_system('LctValueVersusAddress/TestFilter') sim('LctValueVersusAddress')
ans = ' ### Start Compiling sfun_filterV1 mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp6b548f8d_ebfd_4d81_91f7_825cf45d74e4', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214/filterV1.c') Building with 'gcc'. MEX completed successfully. mex('sfun_filterV1.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214', '/tmp/Bdoc24b_2725827_4048235/tp6b548f8d_ebfd_4d81_91f7_825cf45d74e4/filterV1.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_filterV1 ### Exit ### Start Compiling sfun_filterV2 mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp0dc78f3c_bee7_4ed0_99a6_2aec3e514ecf', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214/filterV2.c') Building with 'gcc'. MEX completed successfully. mex('sfun_filterV2.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex19632214', '/tmp/Bdoc24b_2725827_4048235/tp0dc78f3c_bee7_4ed0_99a6_2aec3e514ecf/filterV2.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_filterV2 ### Exit '
Integrate External C Functions That Pass the Output Argument as a Return Argument
This example shows how to use the Legacy Code Tool to integrate legacy C functions that pass their output as a return argument.
With the Legacy Code Tool, you can:
Provide the legacy function specification.
Generate a C-MEX S-function that calls the legacy code during simulation.
Compile and build the generated S-function for simulation.
Generate a TLC block file and optional
rtwmakecfg.m
file that specifies how the generated code for a model calls the legacy code.
Provide the Legacy Function Specification
Legacy Code Tool functions take a specific data structure or array of structures as the argument. You can initialize the data structure by calling the function legacy_code()
using initialize
as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The prototype of the legacy functions being called in this example is:
FLT gainScalar(const FLT in, const FLT gain)
FLT
is a typedef to float
. The legacy source code is in the your_types.h
, gain.h
, and gainScalar.c
.
% sfun_gain_scalar def = legacy_code('initialize'); def.SFunctionName = 'sfun_gain_scalar'; def.OutputFcnSpec = 'single y1 = gainScalar(single u1, single p1)'; def.HeaderFiles = {'gain.h'}; def.SourceFiles = {'gainScalar.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'};
Generate an S-Function for Simulation
To generate a C-MEX S-function according to the description provided by the input argument def
, call the function legacy_code()
again with the first input set to sfcn_cmex_generate
. The S-function calls the legacy functions during simulation. The source code for the S-function is in the file sfun_gain_scalar.c
.
legacy_code('sfcn_cmex_generate', def);
Compile the Generated S-Function for Simulation
After you generate the C-MEX S-function source file, to compile the S-function for simulation with Simulink®, call the function legacy_code()
again with the first input set to compile
.
legacy_code('compile', def);
### Start Compiling sfun_gain_scalar mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex09148220/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex09148220', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp6c6d170e_934b_4495_bd4e_b25ec172b745', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex09148220/gainScalar.c') Building with 'gcc'. MEX completed successfully. mex('sfun_gain_scalar.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex09148220/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex09148220', '/tmp/Bdoc24b_2725827_4048235/tp6c6d170e_934b_4495_bd4e_b25ec172b745/gainScalar.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_gain_scalar ### Exit
Generate a TLC Block File for Code Generation
After you compile the S-function and use it in simulation, you can call the function legacy_code()
again with the first input set to sfcn_tlc_generate
to generate a TLC block file. The block file specifies how the generated code for a model calls the legacy code. If you do not generate a TLC block file and you try to generate code for a model that includes the S-function, code generation fails.
legacy_code('sfcn_tlc_generate', def);
The generated TLC block file for the S-function is sfun_gain_scalar.tlc
.
Generate an rtwmakecfg.m File for Code Generation
After you create the TLC block file, you can call the function legacy_code()
again with the first input set to rtwmakecfg_generate
to generate an rtwmakecfg.m
file to support code generation. If the required source and header files for the S-function are not in the same folder as the S-function, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m
file.
legacy_code('rtwmakecfg_generate', def);
Generate a Masked S-Function Block for Calling the Generated S-Function
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to slblock_generate
to generate a masked S-function block that calls that S-function. The software places the block in a new model. From there you can copy it to an existing model.
legacy_code('slblock_generate', def);
Show the Generated Integration with Legacy Code
The model LctExternalCodeImportGain
shows integration of the model with the legacy code. The subsystem TestGain
serves as a harness for the call to the legacy C function via the generate S-function.
open_system('LctExternalCodeImportGain') open_system('LctExternalCodeImportGain/TestGain') sim('LctExternalCodeImportGain')
### Start Compiling sfun_gain_scalar mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex09148220/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex09148220', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp36764c4a_21fe_4a41_af97_071fe1d9ad0b', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex09148220/gainScalar.c') Building with 'gcc'. MEX completed successfully. mex('sfun_gain_scalar.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex09148220/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex09148220', '/tmp/Bdoc24b_2725827_4048235/tp36764c4a_21fe_4a41_af97_071fe1d9ad0b/gainScalar.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_gain_scalar ### Exit
Integrate External C++ Object Methods
Integrate legacy C++ object methods by using the Legacy Code Tool.
With the Legacy Code Tool, you can:
Provide the legacy function specification.
Generate a C++ MEX S-function that calls the legacy code during simulation.
Compile and build the generated S-function for simulation.
Generate a block TLC file and optional
rtwmakecfg.m
file that calls the legacy code during code generation.
Provide the Legacy Function Specification
Functions provided with the Legacy Code Tool take a specific data structure or array of structures as the argument. The data structure is initialized by calling the function legacy_code()
using initialize
as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The definition of the legacy C++ class in this example is:
class adder { private: int int_state; public: adder(); int add_one(int increment); int get_val(); };
The legacy source code is in the files adder_cpp.h
and adder_cpp.cpp
.
% sfun_adder_cpp def = legacy_code('initialize'); def.SFunctionName = 'sfun_adder_cpp'; def.StartFcnSpec = 'createAdder()'; def.OutputFcnSpec = 'int32 y1 = adderOutput(int32 u1)'; def.TerminateFcnSpec = 'deleteAdder()'; def.HeaderFiles = {'adder_cpp.h'}; def.SourceFiles = {'adder_cpp.cpp'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'}; def.Options.language = 'C++'; def.Options.useTlcWithAccel = false;
Generate an S-Function for Simulation
To generate a C-MEX S-function according to the description provided by the input argument def
, call the function legacy_code()
again with the first input set to sfcn_cmex_generate
. The S-function calls the legacy functions during simulation. The source code for the S-function is in the file sfun_adder_cpp.cpp
.
legacy_code('sfcn_cmex_generate', def);
Compile the Generated S-Function for Simulation
After you generate the C-MEX S-function source file, to compile the S-function for simulation with Simulink®, call the function legacy_code()
again with the first input set to compile
.
legacy_code('compile', def);
### Start Compiling sfun_adder_cpp mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex06428671/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex06428671', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp92af3f10_a09b_4d93_b2e8_3165c419dd33', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex06428671/adder_cpp.cpp') Building with 'g++'. MEX completed successfully. mex('sfun_adder_cpp.cpp', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex06428671/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex06428671', '-cxx', '/tmp/Bdoc24b_2725827_4048235/tp92af3f10_a09b_4d93_b2e8_3165c419dd33/adder_cpp.o') Building with 'g++'. MEX completed successfully. ### Finish Compiling sfun_adder_cpp ### Exit
Generate a TLC Block File for Code Generation
After you compile the S-function and use it in simulation, you can call the function legacy_code()
again. Set the first input to sfcn_tlc_generate
to generate a TLC block file that supports code generation through Simulink® Coder™. If the TLC block file is not created and you try to generate code for a model that includes the S-function, code generation fails. The TLC block file for the S-function is sfun_adder_cpp.tlc
.
legacy_code('sfcn_tlc_generate', def);
Generate an rtwmakecfg.m File for Code Generation
After you create the TLC block file, you can call the function legacy_code()
again. Set the first input to rtwmakecfg_generate
to generate an rtwmakecfg.m file that supports code generation through Simulink® Coder™. If the required source and header files for the S-function are not in the same folder as the S-function, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m
file.
legacy_code('rtwmakecfg_generate', def);
Generate Masked S-Function Block for Calling the Generated S-Function
After you compile the C-MEX S-function source, you can call the function legacy_code()
again. Set the first input to slblock_generate
to generate a masked S-function block that is configured to call that S-function. The software places the block in a new model. You can copy the block to an existing model.
legacy_code('slblock_generate', def);
Show the Generated Integration with Legacy Code
The model LctExternalCodeImportCpp
shows integration with the legacy code.
open_system('LctExternalCodeImportCpp') sim('LctExternalCodeImportCpp')
ans = ' ### Start Compiling sfun_adder_cpp mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex06428671/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex06428671', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tpa89cbee0_a040_4783_a0b8_35ee6a93b8eb', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex06428671/adder_cpp.cpp') Building with 'g++'. MEX completed successfully. mex('sfun_adder_cpp.cpp', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex06428671/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex06428671', '-cxx', '/tmp/Bdoc24b_2725827_4048235/tpa89cbee0_a040_4783_a0b8_35ee6a93b8eb/adder_cpp.o') Building with 'g++'. MEX completed successfully. ### Finish Compiling sfun_adder_cpp ### Exit '
Integrate External C Functions That Pass Input and Output Arguments as Parameters with a Fixed-Point Data Type
Integrate legacy C functions that pass their inputs and outputs by using parameters of a fixed-point data type with the Legacy Code Tool.
With the Legacy Code Tool, you can:
Provide the legacy function specification.
Generate a C-MEX S-function that calls the legacy code during simulation.
Compile and build the generated S-function for simulation.
Generate a TLC block file and optional
rtwmakecfg.m
file that specifies how the generated code for a model calls the legacy code.
Provide the Legacy Function Specification
Legacy Code Tool functions take a specific data structure or array of structures as the argument. You can initialize the data structure by calling the function legacy_code()
using initialize
as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The prototype of the legacy functions being called in this example is:
myFixpt timesS16(const myFixpt in1, const myFixpt in2, const uint8_T fracLength)
myFixpt
is logically a fixed point data type, which is physically a typedef to a 16-bit integer:
myFixpt = Simulink.NumericType; myFixpt.DataTypeMode = 'Fixed-point: binary point scaling'; myFixpt.Signed = true; myFixpt.WordLength = 16; myFixpt.FractionLength = 10; myFixpt.IsAlias = true; myFixpt.HeaderFile = 'timesFixpt.h';
The legacy source code is in the files timesFixpt.h
, and timesS16.c
.
% sfun_gain_fixpt def = legacy_code('initialize'); def.SFunctionName = 'sfun_gain_fixpt'; def.OutputFcnSpec = 'myFixpt y1 = timesS16(myFixpt u1, myFixpt p1, uint8 p2)'; def.HeaderFiles = {'timesFixpt.h'}; def.SourceFiles = {'timesS16.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'};
Generate an S-Function for Simulation
To generate a C-MEX S-function according to the description provided by the input argument def
, call the function legacy_code()
again with the first input set to sfcn_cmex_generate
. The S-function calls the legacy functions during simulation. The source code for the S-function is in the file sfun_gain_fixpt.c
.
legacy_code('sfcn_cmex_generate', def);
Compile the Generated S-Function for Simulation
After you generate the C-MEX S-function source file, to compile the S-function for simulation with Simulink®, call the function legacy_code()
again with the first input set to compile
.
legacy_code('compile', def);
### Start Compiling sfun_gain_fixpt mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex05928773/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex05928773', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tpf78145f7_9223_4164_b16d_7060fdbca062', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex05928773/timesS16.c') Building with 'gcc'. MEX completed successfully. mex('sfun_gain_fixpt.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex05928773/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex05928773', '/tmp/Bdoc24b_2725827_4048235/tpf78145f7_9223_4164_b16d_7060fdbca062/timesS16.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_gain_fixpt ### Exit
Generate a TLC Block File for Code Generation
After you compile the S-function and use it in simulation, you can call the function legacy_code()
again. Set the first input to sfcn_tlc_generate
to generate a TLC block file. The block file specifies how the generated code for a model calls the legacy code. If you do not generate a TLC block file and you try to generate code for a model that includes the S-function, code generation fails. The TLC block file for the S-function is sfun_gain_fixpt.tlc
.
legacy_code('sfcn_tlc_generate', def);
Generate an rtwmakecfg.m File for Code Generation
After you create the TLC block file, you can call the function legacy_code()
again. Set the first input to rtwmakecfg_generate
to generate an rtwmakecfg.m
file that supports code generation. If the required source and header files for the S-function are not in the same folder as the S-function, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m
file.
legacy_code('rtwmakecfg_generate', def);
Generate a Masked S-Function Block for Calling the Generated S-Function
After you compile the C-MEX S-function source, you can call the function legacy_code()
again. Set the first input to slblock_generate
to generate a masked S-function block that calls that S-function. The software places the block in a new model. You can copy the block to an existing model.
legacy_code('slblock_generate', def);
Show the Generated Integration with Legacy Code
The model LctFixedParams
shows integration of the model with the legacy code. The subsystem TestFixpt
serves as a harness for the call to the legacy C function via the generated S-function.
open_system('LctFixedParams') open_system('LctFixedParams/TestFixpt') sim('LctFixedParams')
ans = ' ### Start Compiling sfun_gain_fixpt mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex05928773/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex05928773', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp668e9cac_0042_43e6_8612_31346cc5efe4', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex05928773/timesS16.c') Building with 'gcc'. MEX completed successfully. mex('sfun_gain_fixpt.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex05928773/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex05928773', '/tmp/Bdoc24b_2725827_4048235/tp668e9cac_0042_43e6_8612_31346cc5efe4/timesS16.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_gain_fixpt ### Exit '
Integrate External C Functions That Pass Input and Output Arguments as Signals with a Fixed-Point Data Type
This example shows how to use the Legacy Code Tool to integrate legacy C functions that pass their inputs and outputs by using parameters of fixed-point data type.
With the Legacy Code Tool, you can:
Provide the legacy function specification.
Generate a C-MEX S-function that calls the legacy code during simulation.
Compile and build the generated S-function for simulation.
Generate a TLC block file and optional
rtwmakecfg.m
file that specifies how the generated code for a model calls the legacy code.
Provide the Legacy Function Specification
Legacy Code Tool functions take a specific data structure or array of structures as the argument. You can initialize the data structure by calling the function legacy_code()
using initialize
as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The prototype of the legacy functions being called in this example is:
myFixpt timesS16(const myFixpt in1, const myFixpt in2, const uint8_T fracLength)
myFixpt
is logically a fixed-point data type, which is physically a typedef to a 16-bit integer:
myFixpt = Simulink.NumericType; myFixpt.DataTypeMode = 'Fixed-point: binary point scaling'; myFixpt.Signed = true; myFixpt.WordLength = 16; myFixpt.FractionLength = 10; myFixpt.IsAlias = true; myFixpt.HeaderFile = 'timesFixpt.h';
The legacy source code is in the files timesFixpt.h
, and timesS16.c
.
% sfun_times_s16 def = legacy_code('initialize'); def.SFunctionName = 'sfun_times_s16'; def.OutputFcnSpec = 'myFixpt y1 = timesS16(myFixpt u1, myFixpt u2, uint8 p1)'; def.HeaderFiles = {'timesFixpt.h'}; def.SourceFiles = {'timesS16.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'};
Generate an S-Function for Simulation
To generate a C-MEX S-function according to the description provided by the input argument def
, call the function legacy_code()
again with the first input set to sfcn_cmex_generate
. The S-function calls the legacy functions during simulation. The source code for the S-function is in the file sfun_times_s16.c
.
legacy_code('sfcn_cmex_generate', def);
Compile the Generated S-Function for Simulation
After you generate the C-MEX S-function source file, to compile the S-function for simulation with Simulink®, call the function legacy_code()
again with the first input set to compile
.
legacy_code('compile', def);
### Start Compiling sfun_times_s16 mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex96454812/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex96454812', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp2e4d3fbd_f71f_46a1_9934_41373422d014', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex96454812/timesS16.c') Building with 'gcc'. MEX completed successfully. mex('sfun_times_s16.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex96454812/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex96454812', '/tmp/Bdoc24b_2725827_4048235/tp2e4d3fbd_f71f_46a1_9934_41373422d014/timesS16.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_times_s16 ### Exit
Generate a TLC Block File for Code Generation
After you compile the S-function and use it in simulation, you can call the function legacy_code()
again with the first input set to sfcn_tlc_generate
to generate a TLC block file. The block file specifies how the generated code for a model calls the legacy code. If you do not generate a TLC block file and you try to generate code for a model that includes the S-function, code generation fails. The TLC block file for the S-function is sfun_times_s16.tlc
.
legacy_code('sfcn_tlc_generate', def);
Generate an rtwmakecfg.m File for Code Generation
After you create the TLC block file, you can call the function legacy_code()
again with the first input set to rtwmakecfg_generate
to generate an rtwmakecfg.m file to support code generation. If the required source and header files for the S-function are not in the same folder as the S-function, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m
file.
legacy_code('rtwmakecfg_generate', def);
Generate a Masked S-Function Block for Calling the Generated S-Function
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to slblock_generate
to generate a masked S-function block that calls that S-function. The software places the block in a new model. From there you can copy it to an existing model.
legacy_code('slblock_generate', def);
Show the Integration of the Model with Legacy Code
The model LctFixedSignals
shows integration of the model with the legacy code. The subsystem TestFixpt
serves as a harness for the call to the legacy C function via the generated S-function.
open_system('LctFixedSignals') open_system('LctFixedSignals/TestFixpt') sim('LctFixedSignals')
ans = ' ### Start Compiling sfun_times_s16 mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex96454812/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex96454812', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tpdb725161_89a1_4a40_b0a8_095f2993941f', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex96454812/timesS16.c') Building with 'gcc'. MEX completed successfully. mex('sfun_times_s16.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex96454812/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex96454812', '/tmp/Bdoc24b_2725827_4048235/tpdb725161_89a1_4a40_b0a8_095f2993941f/timesS16.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_times_s16 ### Exit '
Integrate External C Functions with Instance-Specific Persistent Memory
Integrate legacy C functions that use instance-specific persistent memory by using the Legacy Code Tool.
With the Legacy Code Tool, you can:
Provide the legacy function specification.
Generate a C-MEX S-function that calls the legacy code during simulation.
Compile and build the generated S-function for simulation.
Generate a TLC block file and optional
rtwmakecfg.m
file that specifies how the generated code for a model calls the legacy code.
Provide the Legacy Function Specification
Legacy Code Tool functions take a specific data structure or array of structures as the argument. You can initialize the data structure by calling the function legacy_code()
using initialize
as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The prototypes of the legacy functions being called in this example are:
void memory_bus_init(COUNTERBUS *mem, int32_T upper_sat, int32_T lower_sat);
void memory_bus_step(COUNTERBUS *input, COUNTERBUS *mem, COUNTERBUS *output);
mem is an instance-specific persistent memory for applying a one integration step delay. COUNTERBUS is a struct typedef defined in counterbus.h
and implemented with a Simulink.Bus object in the base workspace. The legacy source code is in the files memory_bus.h
, and memory_bus.c
.
evalin('base','load Lct_data.mat') % sfun_work def = legacy_code('initialize'); def.SFunctionName = 'sfun_work'; def.InitializeConditionsFcnSpec = ... 'void memory_bus_init(COUNTERBUS work1[1], int32 p1, int32 p2)'; def.OutputFcnSpec = ... 'void memory_bus_step(COUNTERBUS u1[1], COUNTERBUS work1[1], COUNTERBUS y1[1])'; def.HeaderFiles = {'memory_bus.h'}; def.SourceFiles = {'memory_bus.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'};
Generate an S-Function for Simulation
To generate a C-MEX S-function according to the description provided by the input argument def
, call the function legacy_code()
again with the first input set to sfcn_cmex_generate
. The S-function calls the legacy functions during simulation. The source code for the S-function is in the generated sfun_work.c
file.
legacy_code('sfcn_cmex_generate', def);
Compile the Generated S-Function for Simulation
After you generate the C-MEX S-function source file, to compile the S-function for simulation with Simulink®, call the function legacy_code()
again with the first input set to compile
.
legacy_code('compile', def);
### Start Compiling sfun_work mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex38707886/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex38707886', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp4837f753_3575_49a6_88ee_1c1a43e58627', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex38707886/memory_bus.c') Building with 'gcc'. MEX completed successfully. mex('sfun_work.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex38707886/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex38707886', '/tmp/Bdoc24b_2725827_4048235/tp4837f753_3575_49a6_88ee_1c1a43e58627/memory_bus.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_work ### Exit
Generate a TLC Block File for Code Generation
After you compile the S-function and use it in simulation, you can call the function legacy_code()
again with the first input set to sfcn_tlc_generate
to generate a TLC block file. The block file specifies how the generated code for a model calls the legacy code. If you do not generate a TLC block file and you try to generate code for a model that includes the S-function, code generation fails.
legacy_code('sfcn_tlc_generate', def);
The TLC block file for the S-function is sfun_work.tlc
.
Generate an rtwmakecfg.m File for Code Generation
After you create the TLC block file, you can call the function legacy_code()
again with the first input set to rtwmakecfg_generate
to generate an rtwmakecfg.m
file to support code generation. If the required source and header files for the S-function are not in the same folder as the S-function, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m
file.
legacy_code('rtwmakecfg_generate', def);
Generate a Masked S-Function Block for Calling the Generated S-Function
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to slblock_generate
to generate a masked S-function block that calls that S-function. The software places the block in a new model. From there you can copy it to an existing model.
legacy_code('slblock_generate', def);
Show the Integration of the Model with Legacy Code
The model LctInstanceSpecificMemory
shows integration of the model with the legacy code. The subsystem memory_bus
serves as a harness for the call to the legacy C function.
open_system('LctInstanceSpecificMemory') open_system('LctInstanceSpecificMemory/memory_bus') sim('LctInstanceSpecificMemory')
ans = ' ### Start Compiling sfun_work mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex38707886/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex38707886', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp170bcd77_372c_4b07_9294_f9f20b931564', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex38707886/memory_bus.c') Building with 'gcc'. MEX completed successfully. mex('sfun_work.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex38707886/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex38707886', '/tmp/Bdoc24b_2725827_4048235/tp170bcd77_372c_4b07_9294_f9f20b931564/memory_bus.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_work ### Exit '
Integrate External C Functions That Use Structure Arguments
Integrate legacy C functions with structure arguments that use Simulink® buses with the Legacy Code Tool.
With the Legacy Code Tool, you can:
Provide the legacy function specification.
Generate a C-MEX S-function that calls the legacy code during simulation.
Compile and build the generated S-function for simulation.
Generate a TLC block file and optional
rtwmakecfg.m
file that specifies how the generated code for a model calls the legacy code.
Provide the Legacy Function Specification
Legacy Code Tool functions take a specific data structure or array of structures as the argument. You can initialize the data structure by calling the function legacy_code()
using initialize
as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The prototype of the legacy functions being called in this example is:
counterbusFcn(COUNTERBUS *u1, int32_T u2, COUNTERBUS *y1, int32_T *y2)
COUNTERBUS is a struct typedef defined in counterbus.h
file and implemented with a Simulink.Bus object in the base workspace. The legacy source code is in the files counterbus.h
, and counterbus.c
.
evalin('base','load Lct_data.mat') % rtwdemo_sfun_counterbus def = legacy_code('initialize'); def.SFunctionName = 'sfun_counterbus'; def.OutputFcnSpec = ... 'void counterbusFcn(COUNTERBUS u1[1], int32 u2, COUNTERBUS y1[1], int32 y2[1])'; def.HeaderFiles = {'counterbus.h'}; def.SourceFiles = {'counterbus.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'};
Generate an S-Function for Simulation
To generate a C-MEX S-function according to the description provided by the input argument def
, call the function legacy_code()
again with the first input set to sfcn_cmex_generate
. The S-function calls the legacy functions during simulation. The source code for the S-function is in the file rtwdemo_sfun_counterbus.c
.
legacy_code('sfcn_cmex_generate', def);
Compile the Generated S-Function for Simulation
After you generate the C-MEX S-function source file, to compile the S-function for simulation with Simulink®, call the function legacy_code()
again with the first input set to compile
.
legacy_code('compile', def);
### Start Compiling sfun_counterbus mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex90330074/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex90330074', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tpd3244334_0175_483b_9c96_fed982a72179', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex90330074/counterbus.c') Building with 'gcc'. MEX completed successfully. mex('sfun_counterbus.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex90330074/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex90330074', '/tmp/Bdoc24b_2725827_4048235/tpd3244334_0175_483b_9c96_fed982a72179/counterbus.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_counterbus ### Exit
Generate a TLC Block File for Code Generation
After you compile the S-function and use it in simulation, you can call the function legacy_code()
again with the first input set to sfcn_tlc_generate
to generate a TLC block file. The block file specifies how the generated code for a model calls the legacy code. If you do not generate a TLC block file and you try to generate code for a model that includes the S-function, code generation fails. The TLC block file for the S-function is sfun_counterbus.tlc
.
legacy_code('sfcn_tlc_generate', def);
Generate an rtwmakecfg.m File for Code Generation
After you create the TLC block file, you can call the function legacy_code()
again with the first input set to rtwmakecfg_generate
to generate an rtwmakecfg.m
file to support code generation. If the required source and header files for the S-function are not in the same folder as the S-function, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m
file.
legacy_code('rtwmakecfg_generate', def);
Generate a Masked S-Function Block for Calling the Generated S-Function
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to slblock_generate
to generate a masked S-function block that calls that S-function. The software places the block in a new model. From there you can copy it to an existing model.
legacy_code('slblock_generate', def);
Show the Integration of the Model with Legacy Code
The model LctStructureArguments
shows integration of the model with the legacy code. The subsystem TestCounter
serves as a harness for the call to the legacy C function.
open_system('LctStructureArguments') open_system('LctStructureArguments/TestCounter') sim('LctStructureArguments')
### Start Compiling sfun_counterbus mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex90330074/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex90330074', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp3d3e90fc_d628_4ece_8137_ce9dfd0130f9', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex90330074/counterbus.c') Building with 'gcc'. MEX completed successfully. mex('sfun_counterbus.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex90330074/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex90330074', '/tmp/Bdoc24b_2725827_4048235/tp3d3e90fc_d628_4ece_8137_ce9dfd0130f9/counterbus.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_counterbus ### Exit
Integrate External C Functions That Pass Input and Output Arguments as Signals with Complex Data
Integrate legacy C functions using complex signals with the Legacy Code Tool.
With the Legacy Code Tool, you can:
Provide the legacy function specification.
Generate a C-MEX S-function that calls the legacy code during simulation.
Compile and build the generated S-function for simulation.
Generate a TLC block file and optional
rtwmakecfg.m
file that specifies how the generated code for a model calls the legacy code.
Provide the Legacy Function Specification
Legacy Code Tool functions take a specific data structure or array of structures as the argument. You can initialize the data structure by calling the function legacy_code()
using initialize
as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The prototype of the legacy functions being called in this example is:
void cplx_gain(creal_T *input, creal_T *gain, creal_T *output);
creal_T is the complex representation of a double. The legacy source code is in the files cplxgain.h
, and cplxgain.c
.
% sfun_gain_scalar def = legacy_code('initialize'); def.SFunctionName = 'sfun_cplx_gain'; def.OutputFcnSpec = ... ['void cplx_gain(complex<double> u1[1], '... 'complex<double> p1[1], complex<double> y1[1])']; def.HeaderFiles = {'cplxgain.h'}; def.SourceFiles = {'cplxgain.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'};
Generate an S-Function for Simulation
To generate a C-MEX S-function according to the description provided by the input argument def
, call the function legacy_code() again with the first input set to sfcn_cmex_generate
. The S-function calls the legacy functions during simulation. The source code for the S-function is in the file sfun_cplx_gain.c
.
legacy_code('sfcn_cmex_generate', def);
Compile the Generated S-Function for Simulation
After you generate the C-MEX S-function source file, to compile the S-function for simulation with Simulink®, call the function legacy_code()
again with the first input set to compile
.
legacy_code('compile', def);
### Start Compiling sfun_cplx_gain mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex97344681/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex97344681', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp51cee25d_cbfd_439b_ada5_7a360ef9c24e', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex97344681/cplxgain.c') Building with 'gcc'. MEX completed successfully. mex('sfun_cplx_gain.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex97344681/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex97344681', '/tmp/Bdoc24b_2725827_4048235/tp51cee25d_cbfd_439b_ada5_7a360ef9c24e/cplxgain.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_cplx_gain ### Exit
Generate a TLC Block File for Code Generation
After you compile the S-function and use it in simulation, you can call the function legacy_code()
again with the first input set to sfcn_tlc_generate
to generate a TLC block file. The block file specifies how the generated code for a model calls the legacy code. If you do not generate a TLC block file and you try to generate code for a model that includes the S-function, code generation fails. The TLC block file for the S-function is sfun_cplx_gain.tlc
.
legacy_code('sfcn_tlc_generate', def);
Generate an rtwmakecfg.m File for Code Generation
After you create the TLC block file, you can call the function legacy_code()
again with the first input set to rtwmakecfg_generate
to generate an rtwmakecfg.m
file to support code generation. If the required source and header files for the S-function are not in the same folder as the S-function, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m
file.
legacy_code('rtwmakecfg_generate', def);
Generate a Masked S-Function Block for Calling the Generated S-Function
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to slblock_generate
to generate a masked S-function block that calls that S-function. The software places the block in a new model. From there you can copy it to an existing model.
legacy_code('slblock_generate', def);
Show the Integration of the Model with Legacy Code
The model LctComplexSignal
shows integration of the model with the legacy code. The subsystem complex_gain
serves as a harness for the call to the legacy C function via the generate S-function.
if isempty(find_system('SearchDepth',0,'Name','LctComplexSignal')) open_system('LctComplexSignal') open_system('LctComplexSignal/complex_gain') sim('LctComplexSignal') end
ans = ' ### Start Compiling sfun_cplx_gain mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex97344681/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex97344681', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp539fc559_7cdf_4037_bed5_75f3bc0fafb3', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex97344681/cplxgain.c') Building with 'gcc'. MEX completed successfully. mex('sfun_cplx_gain.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex97344681/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex97344681', '/tmp/Bdoc24b_2725827_4048235/tp539fc559_7cdf_4037_bed5_75f3bc0fafb3/cplxgain.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_cplx_gain ### Exit '
Integrate External C Functions That Pass Arguments That Have Inherited Dimensions
This example shows how to use the Legacy Code Tool to integrate legacy C functions whose arguments have inherited dimensions.
With the Legacy Code Tool, you can:
Provide the legacy function specification.
Generate a C-MEX S-function that calls the legacy code during simulation.
Compile and build the generated S-function for simulation.
Generate a TLC block file and optional
rtwmakecfg.m
file that specifies how the generated code for a model calls the legacy code.
Provide the Legacy Function Specification
Legacy Code Tool functions take a specific data structure or array of structures as the argument. You can initialize the data structure by calling the function legacy_code()
using initialize
as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The prototypes of the legacy functions being called in this example are:
void mat_add(real_T *u1, real_T *u2, int32_T nbRows, int32_T nbCols, real_T *y1)
void mat_mult(real_T *u1, real_T *u2, int32_T nbRows1, int32_T nbCols1, int32_T nbCols2, real_T *y1)
real_T
is a typedef to double, and int32_T
is a typedef to a 32-bit integer. The legacy source code is in the mat_ops.h
, and mat_ops.c
.
defs = []; % sfun_mat_add def = legacy_code('initialize'); def.SFunctionName = 'sfun_mat_add'; def.OutputFcnSpec = ['void mat_add(double u1[][], double u2[][], ' ... 'int32 u3, int32 u4, double y1[size(u1,1)][size(u1,2)])']; def.HeaderFiles = {'mat_ops.h'}; def.SourceFiles = {'mat_ops.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'}; defs = [defs; def]; % sfun_mat_mult def = legacy_code('initialize'); def.SFunctionName = 'sfun_mat_mult'; def.OutputFcnSpec = ['void mat_mult(double u1[p1][p2], double u2[p2][p3], '... 'int32 p1, int32 p2, int32 p3, double y1[p1][p3])']; def.HeaderFiles = {'mat_ops.h'}; def.SourceFiles = {'mat_ops.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'}; defs = [defs; def];
Generate S-Functions for Simulation
To generate C-MEX S-functions according to the description provided by the input argument defs
, call the function legacy_code()
again with the first input set to sfcn_cmex_generate
. The S-functions call the legacy functions during simulation. The source code for the S-function are in the files sfun_mat_add.c
and sfun_mat_mult.c
.
legacy_code('sfcn_cmex_generate', defs);
Compile the Generated S-Functions for Simulation
After you generate the C-MEX S-function source files, to compile the S-functions for simulation with Simulink®, call the function legacy_code()
again with the first input set to compile
.
legacy_code('compile', defs);
### Start Compiling sfun_mat_add mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tpda120b05_a219_4369_918c_01aa5a25eefe', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148/mat_ops.c') Building with 'gcc'. MEX completed successfully. mex('sfun_mat_add.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148', '/tmp/Bdoc24b_2725827_4046264/tpda120b05_a219_4369_918c_01aa5a25eefe/mat_ops.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_mat_add ### Exit ### Start Compiling sfun_mat_mult mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tp038c37bc_b26c_4911_94be_2e9cf4c61149', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148/mat_ops.c') Building with 'gcc'. MEX completed successfully. mex('sfun_mat_mult.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148', '/tmp/Bdoc24b_2725827_4046264/tp038c37bc_b26c_4911_94be_2e9cf4c61149/mat_ops.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_mat_mult ### Exit
Generate TLC Block Files for Code Generation
After you compile the S-functions and use them in simulation, you can call the function legacy_code()
again with the first input set to sfcn_tlc_generate
to generate TLC block files. Block files specify how the generated code for a model calls the legacy code. If you do not generate TLC block files and you try to generate code for a model that includes the S-functions, code generation fails. The TLC block files for the S-functions are sfun_mat_add.tlc
and sfun_mat_mult.tlc
.
legacy_code('sfcn_tlc_generate', defs);
Generate an rtwmakecfg.m File for Code Generation
After you create the TLC block files, you can call the function legacy_code()
again with the first input set to rtwmakecfg_generate
to generate an rtwmakecfg.m
file to support code generation. If the required source and header files for the S-functions are not in the same folder as the S-functions, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m
file.
legacy_code('rtwmakecfg_generate', defs);
Generate Masked S-Function Blocks for Calling the Generated S-Functions
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to slblock_generate
to generate masked S-function blocks that call the S-functions. The software places the blocks in a new model. From there you can copy them to an existing model
legacy_code('slblock_generate', defs);
Show the Generated Integration with Legacy Code
The model LctInheritedDimensions
shows integration of the model with the legacy code. The subsystem TestMatOps
serves as a harness for the calls to the legacy C functions, with unit delays serving to store the previous output values.
open_system('LctInheritedDimensions') open_system('LctInheritedDimensions/TestMatOps') sim('LctInheritedDimensions')
ans = ' ### Start Compiling sfun_mat_add mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tp3c6a6cd7_1984_4aa3_90dd_5324eacdc04a', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148/mat_ops.c') Building with 'gcc'. MEX completed successfully. mex('sfun_mat_add.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148', '/tmp/Bdoc24b_2725827_4046264/tp3c6a6cd7_1984_4aa3_90dd_5324eacdc04a/mat_ops.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_mat_add ### Exit ### Start Compiling sfun_mat_mult mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tp90672d05_45fd_4d2a_ac83_7a642116bb56', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148/mat_ops.c') Building with 'gcc'. MEX completed successfully. mex('sfun_mat_mult.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex89794148', '/tmp/Bdoc24b_2725827_4046264/tp90672d05_45fd_4d2a_ac83_7a642116bb56/mat_ops.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_mat_mult ### Exit '
Integrate External C Functions That Pass Arguments as Multi-Dimensional Signals
This example shows how to use the Legacy Code Tool to integrate legacy C functions with multi-dimensional Signals.
With the Legacy Code Tool, you can:
Provide the legacy function specification.
Generate a C-MEX S-function that calls the legacy code during simulation.
Compile and build the generated S-function for simulation.
Generate a TLC block file and optional
rtwmakecfg.m
file that specifies how the generated code for a model calls the legacy code.
Provide the Legacy Function Specification
Legacy Code Tool functions take a specific data structure or array of structures as the argument. You can initialize the data structure by calling the function legacy_code()
using initialize
as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The prototype of the legacy functions being called in this example is:
void array3d_add(real_T *y1, real_T *u1, real_T *u2, int32_T nbRows, int32_T nbCols, int32_T nbPages);
real_T is a typedef to double, and int32_T is a typedef to a 32-bit integer. The legacy source code is in the files ndarray_ops.h
, and ndarray_ops.c
.
% rtwdemo_sfun_ndarray_add def = legacy_code('initialize'); def.SFunctionName = 'rtwdemo_sfun_ndarray_add'; def.OutputFcnSpec =... ['void array3d_add(double y1[size(u1,1)][size(u1,2)][size(u1,3)], ',... 'double u1[][][], double u2[][][], ' ... 'int32 size(u1,1), int32 size(u1,2), int32 size(u1,3))']; def.HeaderFiles = {'ndarray_ops.h'}; def.SourceFiles = {'ndarray_ops.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'};
y1 is a 3-D output signal of same dimensions as the 3-D input signal u1. Note that the last 3 arguments passed to the legacy function correspond to the number of element in each dimension of the 3-D input signal u1.
Generate an S-Function for Simulation
To generate a C-MEX S-function according to the description provided by the input argument def
, call the function legacy_code()
again with the first input set to sfcn_cmex_generate
. The S-function calls the legacy functions during simulation. The source code for the S-function is in the rtwdemo_sfun_ndarray_add.c
file.
legacy_code('sfcn_cmex_generate', def);
Compile the Generated S-Function for Simulation
After you generate the C-MEX S-function source file, to compile the S-function for simulation with Simulink®, call the function legacy_code()
again with the first input set to compile
.
legacy_code('compile', def);
### Start Compiling rtwdemo_sfun_ndarray_add mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex14927435/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex14927435', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tp1c1d2aa2_fd15_4549_96a6_03efcac0de99', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex14927435/ndarray_ops.c') Building with 'gcc'. MEX completed successfully. mex('rtwdemo_sfun_ndarray_add.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex14927435/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex14927435', '/tmp/Bdoc24b_2725827_4046264/tp1c1d2aa2_fd15_4549_96a6_03efcac0de99/ndarray_ops.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling rtwdemo_sfun_ndarray_add ### Exit
Generate a TLC Block File for Code Generation
After you compile the S-function and use it in simulation, you can call the function legacy_code()
again with the first input set to sfcn_tlc_generate
to generate a TLC block file. The block file specifies how the generated code for a model calls the legacy code. If you do not generate a TLC block file and you try to generate code for a model that includes the S-function, code generation fails.
legacy_code('sfcn_tlc_generate', def);
The generated TLC block file for the S-function is rtwdemo_sfun_ndarray_add.tlc
.
Generate an rtwmakecfg.m File for Code Generation
After you create the TLC block file, you can call the function legacy_code()
again with the first input set to rtwmakecfg_generate
to generate an rtwmakecfg.m
file to support code generation. If the required source and header files for the S-function are not in the same folder as the S-function, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m
file.
legacy_code('rtwmakecfg_generate', def);
Generate a Masked S-Function Block for Calling the Generated S-Function
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to slblock_generate
to generate a masked S-function block that calls that S-function. The software places the block in a new model. From there you can copy it to an existing model.
legacy_code('slblock_generate', def);
Showing the Generated Integration with Legacy Code
The model LctMultiDimensionalSig
shows integration of the model with the legacy code. The subsystem ndarray_add
serves as a harness for the call to the legacy C function.
open_system('LctMultiDimensionalSig') open_system('LctMultiDimensionalSig/ndarray_add') sim('LctMultiDimensionalSig')
ans = ' ### Start Compiling sfun_ndarray_add mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex14927435/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex14927435', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tpb7604220_57fe_4680_b3ae_b2727c12f9a7', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex14927435/ndarray_ops.c') Building with 'gcc'. MEX completed successfully. mex('sfun_ndarray_add.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex14927435/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex14927435', '/tmp/Bdoc24b_2725827_4046264/tpb7604220_57fe_4680_b3ae_b2727c12f9a7/ndarray_ops.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_ndarray_add ### Exit '
Integrate External C Functions That Implement Start and Terminate Actions
Integrate legacy C functions that have start and terminate actions by using the Legacy Code Tool.
With the Legacy Code Tool, you can:
Provide the legacy function specification.
Generate a C-MEX S-function that calls the legacy code during simulation.
Compile and build the generated S-function for simulation.
Generate a TLC block file and optional
rtwmakecfg.m
file that specifies how the generated code for a model calls the legacy code.
Provide the Legacy Function Specification
Legacy Code Tool functions take a specific data structure or array of structures as the argument. You can initialize the data structure by calling the function legacy_code()
using initialize
as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The prototypes of the legacy functions being called in this example are:
void initFaultCounter(unsigned int *counter)
void openLogFile(void **fid)
void incAndLogFaultCounter(void *fid, unsigned int *counter, double time)
void closeLogFile(void **fid)
The legacy source code is in the files your_types.h
, fault.h
, and fault.c
.
% sfun_fault def = legacy_code('initialize'); def.SFunctionName = 'sfun_fault'; def.InitializeConditionsFcnSpec = 'initFaultCounter(uint32 work2[1])'; def.StartFcnSpec = 'openLogFile(void **work1)'; def.OutputFcnSpec = ... 'incAndLogFaultCounter(void *work1, uint32 work2[1], double u1)'; def.TerminateFcnSpec = 'closeLogFile(void **work1)'; def.HeaderFiles = {'fault.h'}; def.SourceFiles = {'fault.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'}; def.Options.useTlcWithAccel = false;
Generate an S-Function for Simulation
To generate a C-MEX S-function according to the description provided by the input argument def
, call the function legacy_code()
again with the first input set to sfcn_cmex_generate
. The S-function calls the legacy functions during simulation.
legacy_code('sfcn_cmex_generate', def);
The source code for the S-function is in the generated sfun_fault.c
file.
Compile the Generated S-Function for Simulation
After you generate the C-MEX S-function source file, to compile the S-function for simulation with Simulink®, call the function legacy_code()
again with the first input set to compile
.
legacy_code('compile', def);
### Start Compiling sfun_fault mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex46254423/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex46254423', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tpa7437ac6_cecd_4065_8d9b_413a08acb3f1', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex46254423/fault.c') Building with 'gcc'. MEX completed successfully. mex('sfun_fault.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex46254423/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex46254423', '/tmp/Bdoc24b_2725827_4046264/tpa7437ac6_cecd_4065_8d9b_413a08acb3f1/fault.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_fault ### Exit
Generate a TLC Block File for Code Generation
After you compile the S-function and use it in simulation, you can call the function legacy_code()
again with the first input set to sfcn_tlc_generate
to generate a TLC block file. The block file specifies how the generated code for a model calls the legacy code. If you do not generate a TLC block file and you try to generate code for a model that includes the S-function, code generation fails.
legacy_code('sfcn_tlc_generate', def);
The generated TLC block file for the S-function is sfun_fault.tlc
.
Generate an rtwmakecfg.m File for Code Generation
After you create the TLC block file, you can call the function legacy_code()
again with the first input set to rtwmakecfg_generate
to generate an rtwmakecfg.m
file to support code generation. If the required source and header files for the S-function are not in the same folder as the S-function, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m
file.
legacy_code('rtwmakecfg_generate', def);
Generate a Masked S-Function Block for Calling the Generated S-Function
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to slblock_generate
to generate a masked S-function block that calls that S-function. The software places the block in a new model. From there you can copy it to an existing model.
legacy_code('slblock_generate', def);
Showing the Generated Integration with Legacy Code
The model LctStartTermActions
shows integration of the model with the legacy code. The subsystem TestFault
serves as a harness for the call to the legacy C function, and the scope compares the output of the function with the output of the built-in Simulink® product block; the results should be identical.
open_system('LctStartTermActions') open_system('LctStartTermActions/TestFault') sim('LctStartTermActions')
ans = ' ### Start Compiling sfun_fault mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex46254423/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex46254423', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tpf5b327d8_cf3b_4f8a_a43d_c0d51692f09a', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex46254423/fault.c') Building with 'gcc'. MEX completed successfully. mex('sfun_fault.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex46254423/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex46254423', '/tmp/Bdoc24b_2725827_4046264/tpf5b327d8_cf3b_4f8a_a43d_c0d51692f09a/fault.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_fault ### Exit '
Integrate External C Functions That Implement N-Dimensional Table Lookups
Integrate legacy C functions that implement N-dimensional table lookups by using the Legacy Code Tool.
With the Legacy Code Tool, you can:
Provide the legacy function specification.
Generate a C-MEX S-function that calls the legacy code during simulation.
Compile and build the generated S-function for simulation.
Generate a TLC block file and optional
rtwmakecfg.m
file that specifies how the generated code for a model calls the legacy code.
Provide the Legacy Function Specification
Legacy Code Tool functions take a specific data structure or array of structures as the argument. You can initialize the data structure by calling the function legacy_code()
using initialize
as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The prototype of the legacy functions being called in this example is:
FLT directLookupTableND(const FLT *tableND, const UINT32 nbDims, const UINT32 *tableDims, const UINT32 *tableIdx)
FLT is a typedef to float, and UINT32 is a typedef to unsigned int32. The legacy source code is in the files your_types.h
, lookupTable.h
, and directLookupTableND.c
.
defs = []; evalin('base','load Lct_data.mat') % sfun_dlut3D def = legacy_code('initialize'); def.SFunctionName = 'sfun_dlut3D'; def.OutputFcnSpec = 'single y1 = DirectLookupTable3D(single p1[][][], uint32 p2[3], uint32 u1[3])'; def.HeaderFiles = {'lookupTable.h'}; def.SourceFiles = {'directLookupTableND.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'}; defs = [defs; def]; % sfun_dlut4D def = legacy_code('initialize'); def.SFunctionName = 'sfun_dlut4D'; def.OutputFcnSpec = 'single y1 = DirectLookupTable4D(single p1[][][][], uint32 p2[4], uint32 u1[4])'; def.HeaderFiles = {'lookupTable.h'}; def.SourceFiles = {'directLookupTableND.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'}; defs = [defs; def];
Generate S-Functions for Simulation
To generate C-MEX S-functions according to the description provided by the input argument defs
, call the function legacy_code()
again. Set the first input to sfcn_cmex_generate
. The S-functions call the legacy functions during simulation. The source code for the S-functions is in the files sfun_dlut3D.c
and rtwdemo_sfun_dlut4D.c
.
legacy_code('sfcn_cmex_generate', defs);
Compile the Generated S-Functions for Simulation
After you generate the C-MEX S-function source files, to compile the S-functions for simulation with Simulink®, call the function legacy_code()
again. Set the first input to compile
.
legacy_code('compile', defs);
### Start Compiling sfun_dlut3D mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tp4b09bd87_d7ea_457f_981e_607028a924f1', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/directLookupTableND.c') Building with 'gcc'. MEX completed successfully. mex('sfun_dlut3D.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '/tmp/Bdoc24b_2725827_4046264/tp4b09bd87_d7ea_457f_981e_607028a924f1/directLookupTableND.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_dlut3D ### Exit ### Start Compiling sfun_dlut4D mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tp7fd0b686_1cd1_4693_91c7_373ad6bcc849', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/directLookupTableND.c') Building with 'gcc'. MEX completed successfully. mex('sfun_dlut4D.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '/tmp/Bdoc24b_2725827_4046264/tp7fd0b686_1cd1_4693_91c7_373ad6bcc849/directLookupTableND.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_dlut4D ### Exit
Generate TLC Block Files for Code Generation
After you compile the S-functions and use them in simulation, you can call the function legacy_code()
again. Set the first input to sfcn_tlc_generate
to generate TLC block files. Block files specify how the generated code for a model calls the legacy code. If you do not generate TLC block files and you try to generate code for a model that includes the S-functions, code generation fails.
legacy_code('sfcn_tlc_generate', defs);
The generated TLC block files for the S-functions are sfun_dlut3D.tlc
and sfun_dlut4D.tlc
.
Generate an rtwmakecfg.m File for Code Generation
After you create the TLC block files, you can call the function legacy_code()
again. Set the first input to rtwmakecfg_generate
to generate an rtwmakecfg.m
file to support code generation. If the required source and header files for the S-functions are not in the same folder as the S-functions, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m
file.
legacy_code('rtwmakecfg_generate', defs);
Generate Masked S-Function Blocks for Calling the Generated S-Functions
After you compile the C-MEX S-function source, you can call the function legacy_code()
again. Set the first input to slblock_generate
to generate masked S-function blocks that call the S-functions. The software places the blocks in a new model. You can copy the blocks to an existing model.
legacy_code('slblock_generate', defs);
Show the Generated Integration with Legacy Code
The model LctTableLookups
shows integration of the model with the legacy code. The subsystem TestLut1
serves as a harness for the call to the legacy C function, and the Display blocks compare the output of the function with the output of the built-in Simulink® lookup blocks. The results are identical.
open_system('LctTableLookups') open_system('LctTableLookups/TestLut1') sim('LctTableLookups')
ans = ' ### Start Compiling sfun_dlut3D mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tp9f4bd3fb_9cb9_4c07_96f3_d5feb4c9fbc1', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/directLookupTableND.c') Building with 'gcc'. MEX completed successfully. mex('sfun_dlut3D.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '/tmp/Bdoc24b_2725827_4046264/tp9f4bd3fb_9cb9_4c07_96f3_d5feb4c9fbc1/directLookupTableND.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_dlut3D ### Exit ### Start Compiling sfun_dlut4D mex('-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4046264/tp9f58c049_baa2_43e6_a599_cfeb6e9b3c0a', '/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/directLookupTableND.c') Building with 'gcc'. MEX completed successfully. mex('sfun_dlut4D.c', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386/Lct_src', '-I/tmp/Bdoc24b_2725827_4046264/tp4bd3b8a0/simulinkcoder-ex19426386', '/tmp/Bdoc24b_2725827_4046264/tp9f58c049_baa2_43e6_a599_cfeb6e9b3c0a/directLookupTableND.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_dlut4D ### Exit '
Integrate External C Functions with a Block Sample Time Specified, Inherited, and Parameterized
This example shows how to use the Legacy Code Tool to integrate legacy C functions with the block's sample time specified, inherited and parameterized.
With the Legacy Code Tool, you can:
Provide the legacy function specification.
Generate a C-MEX S-function that calls the legacy code during simulation.
Compile and build the generated S-function for simulation.
Generate a TLC block file and optional
rtwmakecfg.m
file that specifies how the generated code for a model calls the legacy code.
Provide the Legacy Function Specification
Legacy Code Tool functions take a specific data structure or array of structures as the argument. You can initialize the data structure by calling the function legacy_code()
using initialize
as the first input. After initializing the structure, assign its properties to values corresponding to the legacy code being integrated. The prototype of the legacy functions being called in this example is:
FLT gainScalar(const FLT in, const FLT gain)
FLT is a typedef to float. The legacy source code is in the files your_types.h
, gain.h
, and gainScalar.c
.
defs = []; % sfun_st_inherited def = legacy_code('initialize'); def.SFunctionName = 'sfun_st_inherited'; def.OutputFcnSpec = 'single y1 = gainScalar(single u1, single p1)'; def.HeaderFiles = {'gain.h'}; def.SourceFiles = {'gainScalar.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'}; defs = [defs; def]; % sfun_st_fixed def = legacy_code('initialize'); def.SFunctionName = 'sfun_st_fixed'; def.OutputFcnSpec = 'single y1 = gainScalar(single u1, single p1)'; def.HeaderFiles = {'gain.h'}; def.SourceFiles = {'gainScalar.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'}; def.SampleTime = [2 1]; defs = [defs; def]; % sfun_st_parameterized def = legacy_code('initialize'); def.SFunctionName = 'sfun_st_parameterized'; def.OutputFcnSpec = 'single y1 = gainScalar(single u1, single p1)'; def.HeaderFiles = {'gain.h'}; def.SourceFiles = {'gainScalar.c'}; def.IncPaths = {'Lct_src'}; def.SrcPaths = {'Lct_src'}; def.SampleTime = 'parameterized'; defs = [defs; def];
Generate S-Functions for Simulation
To generate C-MEX S-functions according to the description provided by the input argument defs
, call the function legacy_code()
again with the first input set to sfcn_cmex_generate
. The S-functions call the legacy functions during simulation. The source code for the S-functions is in the files sfun_st_inherited.c
, sfun_st_fixed.c
and sfun_st_parameterized.c
.
legacy_code('sfcn_cmex_generate', defs);
Compile the Generated S-Functions for Simulation
After you generate the C-MEX S-function source files, to compile the S-functions for simulation with Simulink®, call the function legacy_code()
again with the first input set to compile
.
legacy_code('compile', defs);
### Start Compiling sfun_st_inherited mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp6fc3243a_492a_4403_880a_bb5550b9bdcb', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/gainScalar.c') Building with 'gcc'. MEX completed successfully. mex('sfun_st_inherited.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488', '/tmp/Bdoc24b_2725827_4048235/tp6fc3243a_492a_4403_880a_bb5550b9bdcb/gainScalar.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_st_inherited ### Exit ### Start Compiling sfun_st_fixed mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp283e8497_8546_473f_9e9d_5b38f190504b', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/gainScalar.c') Building with 'gcc'. MEX completed successfully. mex('sfun_st_fixed.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488', '/tmp/Bdoc24b_2725827_4048235/tp283e8497_8546_473f_9e9d_5b38f190504b/gainScalar.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_st_fixed ### Exit ### Start Compiling sfun_st_parameterized mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tpd950e30f_0db9_4c90_836a_f38c54fa2c44', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/gainScalar.c') Building with 'gcc'. MEX completed successfully. mex('sfun_st_parameterized.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488', '/tmp/Bdoc24b_2725827_4048235/tpd950e30f_0db9_4c90_836a_f38c54fa2c44/gainScalar.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_st_parameterized ### Exit
Generate TLC Block Files for Code Generation
After you compile the S-functions and use them in simulation, you can call the function legacy_code()
again with the first input set to sfcn_tlc_generate
to generate TLC block files. Block files specify how the generated code for a model calls the legacy code. If you do not generate TLC block files and you try to generate code for a model that includes the S-functions, code generation fails.
legacy_code('sfcn_tlc_generate', defs);
The generated TLC block files for the S-functions are sfun_st_inherited.tlc
, sfun_st_fixed.tlc
, and sfun_st_parameterized.tlc
.
Generate an rtwmakecfg.m File for Code Generation
After you create the TLC block files, you can call the function legacy_code()
again with the first input set to rtwmakecfg_generate
to generate an rtwmakecfg.m
file to support code generation. If the required source and header files for the S-functions are not in the same folder as the S-functions, and you want to add these dependencies in the makefile produced during code generation, generate the rtwmakecfg.m
file.
legacy_code('rtwmakecfg_generate', defs);
Generate Masked S-Function Blocks for Calling the Generated S-Functions
After you compile the C-MEX S-function source, you can call the function legacy_code()
again with the first input set to slblock_generate
to generate masked S-function blocks that call the S-functions. The software places the blocks in a new model. From there you can copy them to an existing model.
legacy_code('slblock_generate', defs);
Show the Generated Integration with Legacy Code
The model LctSampleTime
shows integration of the model with the legacy code. The subsystem sample_time
serves as a harness for the calls to the legacy C functions, with unit delays serving to store the previous output values.
open_system('LctSampleTime') open_system('LctSampleTime/sample_time') sim('LctSampleTime')
ans = ' ### Start Compiling sfun_st_inherited mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tpa7c121a9_7c7c_4985_8f4d_821333525387', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/gainScalar.c') Building with 'gcc'. MEX completed successfully. mex('sfun_st_inherited.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488', '/tmp/Bdoc24b_2725827_4048235/tpa7c121a9_7c7c_4985_8f4d_821333525387/gainScalar.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_st_inherited ### Exit ### Start Compiling sfun_st_fixed mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tpb9909610_a399_45e4_8b2b_6d14e3cc088c', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/gainScalar.c') Building with 'gcc'. MEX completed successfully. mex('sfun_st_fixed.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488', '/tmp/Bdoc24b_2725827_4048235/tpb9909610_a399_45e4_8b2b_6d14e3cc088c/gainScalar.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_st_fixed ### Exit ### Start Compiling sfun_st_parameterized mex('-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488', '-c', '-outdir', '/tmp/Bdoc24b_2725827_4048235/tp7ee84386_b44d_4f7a_8dde_eebab452affd', '/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/gainScalar.c') Building with 'gcc'. MEX completed successfully. mex('sfun_st_parameterized.c', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488/Lct_src', '-I/tmp/Bdoc24b_2725827_4048235/tp88aafc20/simulinkcoder-ex74504488', '/tmp/Bdoc24b_2725827_4048235/tp7ee84386_b44d_4f7a_8dde_eebab452affd/gainScalar.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sfun_st_parameterized ### Exit '