Inherited Signal Dimensions for Legacy Function Arguments
This example shows you how to use the Legacy Code Tool to integrate legacy C functions whose arguments have inherited dimensions.
The Legacy Code Tool allows you to:
Provide the legacy function specification,
Generate a C-MEX S-function that is used during simulation to call the legacy code, and
Compile and build the generated S-function for simulation.
Providing 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, you have to 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)
where real_T is a typedef to double, and int32_T is a typedef to a 32-bit integer. The legacy source code is found in the files mat_ops.h
and mat_ops.c
.
defs = []; % sldemo_sfun_mat_add def = legacy_code('initialize'); def.SFunctionName = 'sldemo_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 = {'sldemo_lct_src'}; def.SrcPaths = {'sldemo_lct_src'}; defs = [defs; def]; % sldemo_sfun_mat_mult def = legacy_code('initialize'); def.SFunctionName = 'sldemo_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 = {'sldemo_lct_src'}; def.SrcPaths = {'sldemo_lct_src'}; defs = [defs; def];
Generating and Compiling an S-Function for Use During Simulation
The function legacy_code() is called again with the first input set to 'generate_for_sim' in order to automatically generate and compile the C-MEX S-function according to the description provided by the input argument 'defs'. This S-function is used to call the legacy functions in simulation. The source code for the S-function is found in the files sldemo_sfun_mat_add.c
and sldemo_sfun_mat_mult.c
.
legacy_code('generate_for_sim', defs);
### Start Compiling sldemo_sfun_mat_add mex('-I/tmp/Bdoc24b_2725827_2525642/tp9a886895/simulink_features-ex63241227/sldemo_lct_src', '-I/tmp/Bdoc24b_2725827_2525642/tp9a886895/simulink_features-ex63241227', '-c', '-outdir', '/tmp/Bdoc24b_2725827_2525642/tpbb66c519_e75d_49a9_8497_a13177dfd023', '/tmp/Bdoc24b_2725827_2525642/tp9a886895/simulink_features-ex63241227/sldemo_lct_src/mat_ops.c') Building with 'gcc'. MEX completed successfully. mex('sldemo_sfun_mat_add.c', '-I/tmp/Bdoc24b_2725827_2525642/tp9a886895/simulink_features-ex63241227/sldemo_lct_src', '-I/tmp/Bdoc24b_2725827_2525642/tp9a886895/simulink_features-ex63241227', '/tmp/Bdoc24b_2725827_2525642/tpbb66c519_e75d_49a9_8497_a13177dfd023/mat_ops.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sldemo_sfun_mat_add ### Exit ### Start Compiling sldemo_sfun_mat_mult mex('-I/tmp/Bdoc24b_2725827_2525642/tp9a886895/simulink_features-ex63241227/sldemo_lct_src', '-I/tmp/Bdoc24b_2725827_2525642/tp9a886895/simulink_features-ex63241227', '-c', '-outdir', '/tmp/Bdoc24b_2725827_2525642/tpe21fc7fd_a59d_419a_8774_d4f42dca9e15', '/tmp/Bdoc24b_2725827_2525642/tp9a886895/simulink_features-ex63241227/sldemo_lct_src/mat_ops.c') Building with 'gcc'. MEX completed successfully. mex('sldemo_sfun_mat_mult.c', '-I/tmp/Bdoc24b_2725827_2525642/tp9a886895/simulink_features-ex63241227/sldemo_lct_src', '-I/tmp/Bdoc24b_2725827_2525642/tp9a886895/simulink_features-ex63241227', '/tmp/Bdoc24b_2725827_2525642/tpe21fc7fd_a59d_419a_8774_d4f42dca9e15/mat_ops.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sldemo_sfun_mat_mult ### Exit
Generating an rtwmakecfg.m File for Code Generation
After the TLC block file is created, the function legacy_code() can be called again with the first input set to 'rtwmakecfg_generate' in order to generate an rtwmakecfg.m file to support code generation through Simulink® Coder™. Generate the rtwmakecfg.m file if the required source and header files for the S-functions are not in the same directory as the S-functions, and you want to add these dependencies in the makefile produced during code generation.
Note: Complete this step only if you need to simulate the model in accelerated mode.
legacy_code('rtwmakecfg_generate', def);
Generating Masked S-Function Blocks for Calling the Generated S-Functions
After the C-MEX S-function source is compiled, the function legacy_code() can be called again with the first input set to 'slblock_generate' in order to generate masked S-function blocks which are configured to call those S-functions. The blocks are placed in a new model and can be copied to an existing model.
% legacy_code('slblock_generate', defs);
Integrate the Legacy Code
The model sldemo_lct_inherit_dims
shows integration 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('sldemo_lct_inherit_dims') open_system('sldemo_lct_inherit_dims/TestMatOps') sim('sldemo_lct_inherit_dims');