已有函数的按值或按地址传递的输入
此示例说明如何使用代码继承工具集成按值与按地址传递其输入参数的已有 C 函数。
代码继承工具允许您:
提供已有函数设定;
生成 C-MEX S-Function,在仿真期间使用它来调用现有代码;以及
编译和构造生成的 S-Function 以进行仿真。
提供已有函数设定
代码继承工具附带的函数接受特定的数据结构体或结构体数组作为参数。可以通过调用函数 legacy_code() 并使用 'initialize' 作为第一个输入来初始化数据结构体。初始化结构体之后,您必须将其属性指定给与要集成的现有代码对应的值。此示例中调用的已有函数的原型为:
FLT filterV1(const FLT signal, const FLT prevSignal, const FLT gain)
FLT filterV2(const FLT* signal, const FLT prevSignal, const FLT gain)
其中 FLT 是浮点类型的 typedef。已有源代码位于文件 your_types.h
、myfilter.h
、filterV1.c
和 filterV2.c
中。
请注意两个结构体中定义的 OutputFcnSpec 的区别:第一种情况指定第一个输入参数按值传递,第二种情况指定按指针传递。
defs = []; % sldemo_sfun_filterV1 def = legacy_code('initialize'); def.SFunctionName = 'sldemo_sfun_filterV1'; def.OutputFcnSpec = 'single y1 = filterV1(single u1, single u2, single p1)'; def.HeaderFiles = {'myfilter.h'}; def.SourceFiles = {'filterV1.c'}; def.IncPaths = {'sldemo_lct_src'}; def.SrcPaths = {'sldemo_lct_src'}; defs = [defs; def]; % sldemo_sfun_filterV2 def = legacy_code('initialize'); def.SFunctionName = 'sldemo_sfun_filterV2'; def.OutputFcnSpec = 'single y1 = filterV2(single u1[1], single u2, single p1)'; def.HeaderFiles = {'myfilter.h'}; def.SourceFiles = {'filterV2.c'}; def.IncPaths = {'sldemo_lct_src'}; def.SrcPaths = {'sldemo_lct_src'}; defs = [defs; def];
生成和编译 S-Function 以供仿真期间使用
再次调用函数 legacy_code() 并将第一个输入设置为 'generate_for_sim',以便根据输入参数 'defs' 提供的描述自动生成和编译 C-MEX S-Function。此 S-Function 用于在仿真中调用已有函数。S-Function 的源代码位于文件 sldemo_sfun_filterV1.c
和 sldemo_sfun_filterV2.c
中。
legacy_code('generate_for_sim', defs);
### Start Compiling sldemo_sfun_filterV1 mex('-I/tmp/Bdoc23a_2181783_2555781/tp1f1d062e/simulink_features-ex08075368/sldemo_lct_src', '-I/tmp/Bdoc23a_2181783_2555781/tp1f1d062e/simulink_features-ex08075368', '-c', '-outdir', '/tmp/Bdoc23a_2181783_2555781/tpa6eca22f_a5a6_477d_a2e3_ac0932236275', '/tmp/Bdoc23a_2181783_2555781/tp1f1d062e/simulink_features-ex08075368/sldemo_lct_src/filterV1.c') Building with 'gcc'. MEX completed successfully. mex('sldemo_sfun_filterV1.c', '-I/tmp/Bdoc23a_2181783_2555781/tp1f1d062e/simulink_features-ex08075368/sldemo_lct_src', '-I/tmp/Bdoc23a_2181783_2555781/tp1f1d062e/simulink_features-ex08075368', '/tmp/Bdoc23a_2181783_2555781/tpa6eca22f_a5a6_477d_a2e3_ac0932236275/filterV1.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sldemo_sfun_filterV1 ### Exit ### Start Compiling sldemo_sfun_filterV2 mex('-I/tmp/Bdoc23a_2181783_2555781/tp1f1d062e/simulink_features-ex08075368/sldemo_lct_src', '-I/tmp/Bdoc23a_2181783_2555781/tp1f1d062e/simulink_features-ex08075368', '-c', '-outdir', '/tmp/Bdoc23a_2181783_2555781/tpd35aa092_06a7_44e4_a96e_17988fda9292', '/tmp/Bdoc23a_2181783_2555781/tp1f1d062e/simulink_features-ex08075368/sldemo_lct_src/filterV2.c') Building with 'gcc'. MEX completed successfully. mex('sldemo_sfun_filterV2.c', '-I/tmp/Bdoc23a_2181783_2555781/tp1f1d062e/simulink_features-ex08075368/sldemo_lct_src', '-I/tmp/Bdoc23a_2181783_2555781/tp1f1d062e/simulink_features-ex08075368', '/tmp/Bdoc23a_2181783_2555781/tpd35aa092_06a7_44e4_a96e_17988fda9292/filterV2.o') Building with 'gcc'. MEX completed successfully. ### Finish Compiling sldemo_sfun_filterV2 ### Exit
生成 rtwmakecfg.m 文件以进行代码生成
在创建 TLC 模块文件后,可再次调用函数 legacy_code() 并将第一个输入设置为 'rtwmakecfg_generate',以生成 rtwmakecfg.m 文件来通过 Simulink® Coder™ 支持代码生成。如果 S-Function 需要的源文件和头文件与 S-Function 不在同一个文件夹中,而您要将这些依存项添加到代码生成过程中生成的联编文件中,请生成 rtwmakecfg.m 文件。
注意:仅当要在加速模式下仿真模型时,才完成此步骤。
legacy_code('rtwmakecfg_generate', def);
生成封装的 S-Function 模块以调用生成的 S-Function
在编译 C-MEX S-Function 源代码后,可以再次调用函数 legacy_code() 并将第一个输入设置为 'slblock_generate',以生成封装的 S-Function 模块,这些模块配置为调用上述 S-Function。这些模块放置在新模型中,并且可以复制到现有模型中。
% legacy_code('slblock_generate', defs);
集成现有代码
模型 sldemo_lct_filter
显示与现有代码的集成。子系统 TestFilter 的作用相当于通过生成的 S-Function 调用已有 C 函数的工具,而单位延迟的作用是存储之前的输出值。
open_system('sldemo_lct_filter') open_system('sldemo_lct_filter/TestFilter') sim('sldemo_lct_filter');