Main Content

本页采用了机器翻译。点击此处可查看英文原文。

导入和测试自定义 C/C++ 代码

您可以使用测试管理器中的代码导入器向导或 MATLAB® 命令行中的 API 命令将自定义 C 或 C++ 代码导入 Simulink® 来测试。您可以执行单元测试来测试 C 代码的子集,或执行集成测试来测试完整的 C 或 C++ 代码。当您导入代码时,代码导入器会:

  • 将 C 代码函数转换为 Simulink C Caller 模块并将这些模块保存在 Simulink 库中

  • 为每个 Simulink C Caller 模块创建一个内部框架

  • 生成测试文件

对于单元测试,代码导入器还会创建一个沙箱来隔离导入的函数。

使用向导或 API 导入代码

要使用代码导入器向导导入和测试自定义 C 或 C++ 代码,请打开测试管理器并选择 新建 > 为 C/C++ 代码创建测试使用向导对导入的自定义代码进行单元测试 示例中显示了向导步骤。使用向导导入代码后,测试管理器的测试浏览器窗格将显示生成的测试文件、测试套件和测试用例,并自动填充每个测试用例的库模型和测试框架字段以及覆盖率设置。您可以通过添加输入、评估、需求链接或其他选项来定制测试管理器中的测试用例。

使用 API 命令导入单元测试的自定义代码 示例展示了导入代码的类和方法。代码导入器设置生成的库、测试文件、测试套件、测试用例和覆盖率的属性值。您可以使用 API 命令添加输入、评估、需求链接或其他选项来定制测试用例。

在运行测试用例之前,将当前文件夹更改为包含生成的工件的文件夹,或者将生成的数据字典添加到路径中。然后运行测试用例并查看覆盖率和其他测试结果。

代码导入器生成的工件

代码导入器创建以下工件:

  • 每个导入的自定义代码函数都有一个带有 C Caller 模块的 Simulink 库。

  • 每个 C Caller 模块都有一个内部测试框架。对于每个生成的框架,求解器是 FixedStepDiscrete,并且启用覆盖率。

  • MLDATX 测试文件。测试文件包括每个 C Caller 模块的测试套件和测试用例。代码导入器还设置了这些覆盖率类型:

    • 决策覆盖率

    • 条件覆盖率

    • MCDC 覆盖率

    • 查找表覆盖率

    • 信号范围覆盖率

    • Simulink Design Verifier 模块的覆盖率

    • 关系边界覆盖率

    • 信号范围覆盖率

  • Simulink 数据字典

此外,仅对于单元测试,代码导入器会创建:

  • 用于隔离被测试功能的沙箱

  • 如果任何源文件有未定义的符号

限制和解决方法

这些限制和解决方法适用于使用自定义 C 或 C++ 代码导入器。

一般限制和解决方法

  • 对于集成测试,如果您的代码包含 C++ 函数,请在将这些函数导入 Simulink 之前在其周围添加包装器以使它们与 C 兼容。

  • 这些 C 类型以及使用这些类型的具有形式参量的函数无法被导入。使用这些类型的全局变量不会作为 C Caller 模块上的端口公开:

    • 具有联合或指针成员的结构

    • 具有多于一级指针间接寻址的输入的函数(例如 >=**

    • 返回指针的函数

    • 名称长度超过 63 个字符的类型,以及使用这些类型的函数和变量

  • 如果您的代码有许多全局变量,请使用 Stateflow® 图而不是 Initialize Function 模块将变量设置为 Simulink 模型中的初始值。

  • 如果头文件或 C 或 C++ 文件包含函数体中定义的汇编代码,则代码导入器不会导入该函数。仅当汇编代码与主机不兼容时,此限制才适用。要导入该函数,

    • 对于集成测试,使用 #ifdef 指令替换汇编代码。

    • 对于单元测试,该函数会自动移动到具有空主体的 auto_stub.c 文件中。要将该函数导入 Simulink,请在 man_stub.c 中手动将该函数桩件。

  • 对于特定于目标的代码,如果代码访问绝对内存地址,请注释掉该代码以防止仿真失败。

头文件

  • 如果多次包含相同的头文件,并且每次包含之前都有不同的预处理器指令(例如,#define X 1#define X 2),则代码可能无法正确导入。

  • 如果在头文件中定义了汇编代码,请使用 #ifdef 指令定义兼容的宏。例如,如果您的代码是:

    #define XYZ(K,L) {\
    asm("MOVLW " ___mkstr(K) ); \
    asm("MOVLW " ___mkstr(L) ); \
    }
    
    替换为:
    #ifndef IS_SL_IMPORT
    #define XYZ(K,L)  {\
    asm("MOVLW " ___mkstr(K) ); \
    asm("MOVLW " ___mkstr(L) ); \
    }
    #else
    // a valid implementation
    #endif
    
    然后,在导入代码时将 IS_SL_IMPORT 添加到定义列表中。

单元测试

这些限制和解决方法仅适用于单元测试。

  • 仅支持导入 C 代码。

  • 如果源文件或头文件包含在导入的源文件中多次包含的函数定义,请更新代码,使函数定义仅出现一次。

  • 所有使用 #include 包含的文件都应该是自包含的,也就是说,它们可以自行编译。具体来说,标题应该具有标题保护并包含其所需的所有其他标题。

另请参阅

| |

相关主题