Main Content

已有函数的按值或按地址传递的输入

此示例说明如何使用代码继承工具集成按值与按地址传递其输入参量的已有 C 函数。

代码继承工具允许您:

  • 提供已有函数设定;

  • 生成 C-MEX S-Function,在仿真期间使用它来调用现有代码;以及

  • 编译和构造生成的 S-Function 以进行仿真。

提供已有函数设定

代码继承工具附带的函数接受特定的数据结构体或结构体数组作为参量。数据结构体是使用 initialize 作为第一个输入通过调用函数 legacy_code() 来初始化的。初始化结构体之后,您必须将其属性指定给与要集成的现有代码对应的值。此示例中调用的已有函数的原型为:

  • 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.hmyfilter.hfilterV1.cfilterV2.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.csldemo_sfun_filterV2.c 中。

legacy_code('generate_for_sim', defs);
### Start Compiling sldemo_sfun_filterV1
    mex('-I/tmp/Bdoc24a_2528353_1244492/tp39b65575/simulink_features-ex08075368/sldemo_lct_src', '-I/tmp/Bdoc24a_2528353_1244492/tp39b65575/simulink_features-ex08075368', '-c', '-outdir', '/tmp/Bdoc24a_2528353_1244492/tp0a45c7d9_1390_49e4_8b04_8ab6373adcbf', '/tmp/Bdoc24a_2528353_1244492/tp39b65575/simulink_features-ex08075368/sldemo_lct_src/filterV1.c')
Building with 'gcc'.
MEX completed successfully.
    mex('sldemo_sfun_filterV1.c', '-I/tmp/Bdoc24a_2528353_1244492/tp39b65575/simulink_features-ex08075368/sldemo_lct_src', '-I/tmp/Bdoc24a_2528353_1244492/tp39b65575/simulink_features-ex08075368', '/tmp/Bdoc24a_2528353_1244492/tp0a45c7d9_1390_49e4_8b04_8ab6373adcbf/filterV1.o')
Building with 'gcc'.
MEX completed successfully.
### Finish Compiling sldemo_sfun_filterV1
### Exit

### Start Compiling sldemo_sfun_filterV2
    mex('-I/tmp/Bdoc24a_2528353_1244492/tp39b65575/simulink_features-ex08075368/sldemo_lct_src', '-I/tmp/Bdoc24a_2528353_1244492/tp39b65575/simulink_features-ex08075368', '-c', '-outdir', '/tmp/Bdoc24a_2528353_1244492/tp4b25f2e9_ce70_4e78_911a_3a5680f2b021', '/tmp/Bdoc24a_2528353_1244492/tp39b65575/simulink_features-ex08075368/sldemo_lct_src/filterV2.c')
Building with 'gcc'.
MEX completed successfully.
    mex('sldemo_sfun_filterV2.c', '-I/tmp/Bdoc24a_2528353_1244492/tp39b65575/simulink_features-ex08075368/sldemo_lct_src', '-I/tmp/Bdoc24a_2528353_1244492/tp39b65575/simulink_features-ex08075368', '/tmp/Bdoc24a_2528353_1244492/tp4b25f2e9_ce70_4e78_911a_3a5680f2b021/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 不在同一个目录中,而您要将这些依存项添加到代码生成过程中生成的 makefile 中,请生成 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');

另请参阅