导入和测试自定义 C/C++ 代码
您可以使用测试管理器中的代码导入器向导或 Simulink® 命令行中的 API 命令将自定义 C 或 C++ 代码导入 MATLAB® 来测试。您可以执行单元测试来测试 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 模块上的端口公开:
具有联合或指针成员的结构
具有多于一级指针间接寻址的输入的函数(例如
>=**
)返回指针的函数
名称长度超过 2048 个字符的类型,以及使用这些类型的函数和变量
如果您的代码有许多全局变量,请使用 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
包含的文件都应该是自包含的,也就是说,它们可以自行编译。具体来说,标题应该具有标题保护并包含其所需的所有其他标题。
另请参阅
sltest.CodeImporter
| sltest.CodeImporter.SandboxSettings
| createSandbox