主要内容

集成C代码使用C调用者

您可以将新的或现有的C代码集成到Simulink中金宝app®使用C调用者块。要在Simulink模型中创建自定义块,请使用金宝appC调用者块允许您调用外部源代码和库中指定的外部C函数。的优点C调用者块:

  • 自动集成简单的C函数

  • 集成金宝app仿真软件覆盖™金宝app仿真软件测试™,金宝app仿真软件设计校验™

  • 集成金宝app仿真软件编码器™

C调用者块和C函数块允许您将C语言算法带入Simulink。金宝app要对动态系统建模,请使用s函数生成器代替。方法将C代码集成到Simulink中的工作流金宝appC调用者块。

请注意

C99是支持自定义C代码集成到Simulink的C语言的标准版本。金宝app金宝app

指定源代码和依赖项

指定包含C函数的外部源代码文件。

  1. 从Simu金宝applink工具条,打开配置参数

  2. 在左侧窗格中,选择模拟目标

  3. 要通过C Caller块启用代码解析,请确保导入自定义代码框被选中。

    目录和文件路径可以是模型目录或当前工作目录的绝对和相对文件路径。看到指定自定义代码的相对路径(Stateflow)

  4. 选择头文件然后输入头文件的名称# include标签。

    提示

    输入信息后源文件在下一步中,您可以单击从源文件自动填充使用源文件中包含的信息自动填充头文件名称。

  5. 额外的构建信息中,选择源文件并输入源文件的路径和名称。如果模型和源文件在不同的目录中,请在文件名之前输入包含源文件的目录。

  6. 选择包括目录,并输入存储附加构建信息(如头文件)的文件夹。

    要验证您的自定义代码是否可以成功解析和构建,请单击验证

请注意

如果你的头文件声明了一个函数,但是你的源文件没有定义这个函数,默认情况下这个函数在C调用者块对话框。您可以设置未定义的函数处理参数指定在这种情况下的其他行为,包括抛出错误、生成存根函数或忽略该条件。

请注意

使用一个C调用者对于每个子系统,或者具有连续的采样时间,或者为了在条件输入分支执行中优化块的使用,块调用的自定义代码函数必须是确定性的,也就是说,总是为相同的输入产生相同的输出。属性来确定哪些自定义代码函数是确定的确定的功能指定的功能参数模拟目标窗格。有关条件输入分支执行的示例,请参见使用带有条件执行的C调用程序块

一天数组处理

金宝app在中的Simulink可以将N-D数组数据传递给自定义代码函数C调用者块,并从这些块接收数据。当您这样做时,您必须指定正确的数组布局来实现预期的结果。看到默认函数数组布局异常的函数.的数组数据的使用示例C调用者块,看到在Simulink中引入自定义图像过滤算法作为可重用块金宝app使用C调用块调用遗留查询表函数

您可以指定在C函数中如何处理矩阵数据的顺序。传递给C函数和从C函数传递的矩阵数据在必要时转换为指定的数组布局。如果没有指定数组布局,矩阵数据将以与您的Simulink数据相同的顺序通过C函数,并且可能由于行-列之间的主要分歧而发生计算错误。金宝app确保所有Simulink数据都遵循相同的默认函数数组布局。金宝app

  • 列为主- C函数按照列主顺序处理输入数组数据。假设你有一个3 × 3矩阵。在C函数中,这个矩阵按如下顺序访问:第一列、第二列和第三列。

  • - C函数按照行主顺序处理输入数组数据。假设你有一个3 × 3矩阵。在C函数中,这个矩阵按如下顺序访问:第一行、第二行和第三行。

  • 任何- C函数与输入数组数据的布局无关。例如,如果函数只对数据执行元素操作,就会出现这种情况。

  • 未指定- C函数不假设输入数组数据的布局。相比任何设置时,只能在列主设置中生成代码。试图在行主集设置中生成代码将产生错误。看到阵列布局(金宝app仿真软件编码器).只有在需要与旧型号兼容时才选择此选项。

要了解关于Simulink中的行主数组和列主数组布局的更多信息,请参见金宝app默认函数数组布局

  1. 选择下面的阵列布局选项默认函数数组布局

  2. 如果需要对代码中的一些函数应用特定的数组布局,请单击异常的函数来选择这些功能。

  3. 点击应用接受你的改变。

如果您的C函数只接受标量和/或向量输入,则默认函数数组布局设置没有效果。

调用C调用者阻塞和指定端口

您可以通过键入以下命令开始将您的定制C代码集成到Simulink中金宝appC调用者在Simuli金宝appnk画布中。或者,拖C调用者块从用户定义函数库转移到画布上。双击块,打开块参数对话框,查看函数和端口规格的名称。

  1. 单击Refresh按钮以导入源代码及其依赖项。

  2. C函数显示在函数名.如果您没有看到完整的函数列表,请单击刷新按钮重新导入源代码。

  3. 要查看源文件中的函数定义,请单击查看功能定义按钮.所选函数的源代码在MATLAB中显示®编辑器。如果源代码不可用,则显示头文件中的函数声明。

  4. 若要更改源文件及其依赖项,或定义和选择函数数组布局,请单击自定义代码设置按钮打开模拟目标窗格中的模型配置参数。

将C函数参数映射到金宝app港口

控件可以将C函数参数从源代码映射到Simulink端口金宝app端口规范表中C调用者块并通过创建FunctionPortSpecification对象。在源代码中,头文件包括要连接到Simulink端口的C函数参数。金宝app

extern void mean_filter(const unsigned char* src, unsigned char* dst, unsigned int width, unsigned int height, unsigned int filterSize);

端口规范展示你的论点的细节,以及它们如何与你的C调用者块模型。金宝app

的名字-指定输入和输出参数的名称。的名字是在源代码中的C函数中定义的函数参数或参数名。本栏仅供参考。

范围-指定C函数参数如何映射到Simulink作用域。金宝app参数的默认作用域取决于函数定义,您可以在源代码中根据函数定义更改作用域。

金宝app模型范围 块映射的作用域
输入 块的输入端口
输出 块输出端口
输入输出 块输入输出端口
全球 块使用的全局变量
参数 块可调参数
常数 恒定值

对于通过指针传递的参数,当有常量限定符定义时,例如const双u *时,参数只能是输入或参数。当没有常量限定符时,参数为输入输出默认情况下,您可以将其更改为an输入输出,或参数范围。在……的情况下输入参数作用域,确保C函数不会修改指针所指向的内存。如果参数是输出作用域,该指针指向的每个元素都应在每次调用该函数时重新赋值。

C参数

金宝app模型范围

函数返回

输出

双u

输入参数常数

双u *

双u []

双u [] [2]

双u [2] [3]

输入输出(默认),输出输入参数

const双u *

const双u []

const双u [] [2]

const双u [2] [3]

输入(默认),参数

使用输入输出端口映射C函数中通过指针传递的输入。使用输入输出端口的输入和输出端口有相同的名称。输入输出端口可以重用输入和输出端口的缓冲区。这可能会优化内存使用取决于信号大小和块布局。

将C函数参数映射到输入输出端口,在函数定义中将变量定义为指针。

extern void mean_filter(unsigned char* src, unsigned int width, unsigned int height, unsigned int filterSize);

然后,选择端口规范输入输出范围在端口规范表,并将结果函数输出赋给自定义函数中的输入变量。

您可以在自定义代码中使用全局变量,将它们映射到适当的Simulink作用域。金宝app要在模型中启用全局变量,请选择启用全局变量作为函数接口模型设置>配置参数>模拟目标.您可以将全局变量映射到输入输出输入输出全球范围在C调用者块。这些作用域的可用性取决于自定义代码中全局变量的使用。

一个全球作用域使您能够在自定义代码和C调用者块,并允许在块上计算期间使用全局变量。值转移使用全球作用域在块接口上不可见。该表显示了示例代码片段及其默认端口和可用端口。

示例代码 金宝app模型范围

双数据;Void foo(Void) {int temp = data;}

全局变量数据只读取变量数据.可用范围:

输入(默认)

全球

双数据;Void bar(Void) {data = 0;}

数据被写入全局变量。可用范围:

输出(默认)

全球

输入输出

双数据;Void foo2(Void) {data = data + 1;}

在全局变量上读取和写入数据。可用范围:

全球(默认)

输入输出

输出

标签- Simulink块中对应参数的标签。金宝app默认情况下,参数标签与参数名相同,除非您更改它。

金宝app模型范围 金宝app仿真软件端口标签

输入输出

端口名称
输入输出 输入端口和输出端口的端口名
全球 端口名和全局变量名

参数

参数名称

常数

常数值的表达式。

例如,使用输入参数名的大小表达式大小(in1, 1)

类型-演示Simulink数据类型和C函数参数数据类型之间的匹配。金宝app

C参数数据类型 金宝app模型数据类型
签署了字符 int8
无符号字符 uint8
字符 Int8或uint8,这取决于编译器
int int32
无符号整型 uint32
int16
Int32或fixdt(1,64,0),具体取决于操作系统
浮动
int8_t int8
uint8_t uint8
int16_t int16
uint16_t uint16
int32_t int32
uint32_t uint32
typedef struct{…** 总线:AStruct
typedef enum {. .} AnEnum** 枚举:AnEnum

*如果C调用者接受一个整数类型,例如int16_t,您可以将其修改为具有匹配基类型的定点类型,例如fixdt(1,16,3)。

* *的C调用者sync按钮提示您导入C函数使用的结构或枚举类型作为Simulink总线和枚举类型。金宝app

大小-指定参数中的数据维度。

C参数维度 金宝app仿真软件端口尺寸

双u

标量(1)

双u []

双u [] [2]

(1)继承(默认)

如果参数是用于输出端口,则应该指定大小。输出端口的大小不能被继承。

双u *

(1)继承(默认)

如果参数是an输入输出端口,大小不能被继承,即使输出端口可以被继承。

对于全局变量,size是标量(1)。

双u [2] [3]

大小为[2,3]。

创建一个FunctionPortSpecification对象和编辑C调用者块的属性

改变端口规范表属性,您可以创建FunctionPortSpecification对象并修改其属性。创建一个FunctionPortSpecification对象的C调用者块,在命令行中输入:

myCCallerConfigObj = get_param (gcb),“FunctionPortSpecification”
myCCallerConfigObj = FunctionPortSpecification with properties: CPrototype: 'real_T add(real_T u1, real_T u2);' inputararguments: [1×金宝app2 Simulink.CustomCode. html];ReturnArgument: [1×1 Simulink.CustomCod金宝appe.]FunctionArgument] GlobalArguments: [1×0 Simulink.CustomCode.FunctionArgument]
CPrototype属性为只读,并显示C函数输入变量的声明。的InputArgumentReturnArgument创建一个属性FunctionArgument对象,您可以根据为其定义的规则进一步编辑其属性端口规范表上面。你可以看到FunctionPortSpecification要学习更多的知识。

修改全局参数C调用者对象的句柄GlobalArguments对象使用getGlobalArg并修改它的属性。

创建一个自定义C调用程序库

建议创建一个库模型来分组C调用者模块和保持你的模型有组织。还可以将数据字典链接到库,以保存代码中定义的自定义类型。当您有多个模型或使用定制C代码的模型引用层次结构时,使用库模型特别有用。

  1. 开启一个新的图书馆模式。在模拟选项卡上,选择>图书馆

  2. 建模选项卡,在设计,点击模拟自定义代码

  3. 选择Cc++语言选项,这取决于您的代码,并确保导入自定义代码框被选中。

  4. 请按照指定源代码和依赖项添加源文件及其依赖项。

  5. 创建C调用者块调用C函数。

  6. 要将库模型中的块插入到Simulink模型中,只需将块拖动到模型中。金宝app

您还可以创建的库C调用者使用Simulink代码导入器从您的自定义代码中删除块。金宝app看到使用Simulink代码导入器导入自定义C/ c++代码金宝app

为自定义代码生成调试符号

要将外部调试器附加到MATLAB进程中,并调试外部C代码,请确保模型配置参数在单独的进程中模拟自定义代码,然后使用以下命令生成调试符号:

清晰的墨西哥人金宝appSimulink.CustomCode.debugSymbols (“上”
打开这个设置并更新模型后,调试符号就生成了,您可以通过将进程附加到MATLAB.exe.使用外部调试器在外部C代码中设置断点,当您模拟模型时,它应该在断点处停止。

使用以下方法关闭此设置:

金宝appSimulink.CustomCode.debugSymbols (“关闭”

从模型生成代码

C调用者金宝app支持代码生成。在从模型生成的代码中,每次执行C调用者block对应于调用与该block相关联的外部C函数。为了构建生成的代码,代码生成>自定义代码“模型配置参数”的窗格中必须填充与自定义代码有关的正确信息。看到模型配置参数:代码生成自定义代码(金宝app仿真软件编码器)

在单独的进程中模拟自定义代码

在模拟包含定制C或c++代码的模型时,您可以选择在MATLAB之外的单独进程中运行定制代码。这个选项在调试自定义代码时可能很有用。通过在单独的进程中运行,自定义代码的问题不会导致MATLAB崩溃,而且您可以更容易地调试和解决此类问题。由于自定义代码中的意外异常或Simulink与自定义代码之间的接口错误,可能会出现问题。金宝app

要启用此选项,在模型配置参数中,在模拟目标窗格中,选择在单独的进程中模拟自定义代码.该选项适用于自定义C/ c++代码集成到您的模型使用以下任何块:

  • C调用者

  • C函数

  • MATLAB函数

  • MATLAB系统

  • Stateflow®图表

例如,这个模型包含一个调用函数的C Caller块加法器(),它访问一个名为adderObj.在调用函数之前,必须创建对象,这可以通过调用initAdder ()初始化函数模拟目标窗格中的模型配置参数。

如果initAdder ()之前没有被调用加法器(),然后加法器()试图访问未初始化的指针,这将导致运行时异常。如果在单独的进程中模拟自定义代码参数未选择,此异常可能导致MATLAB在模拟模型时崩溃。但是,如果选择了参数,模拟模型会在Simulink中产生错误消息。金宝app

然后点击开放启动外部调试器并解决导致错误的问题。

调试器启动后,它将重新启动模拟,并自动在自定义函数项的断点处停止。

一旦您的自定义代码被完全调试,您就可以清除在单独的进程中模拟自定义代码用于更快的模拟时间。

限制

  • 全局变量—作为函数输入输出的全局变量不支持多维数组。金宝app

  • 自定义代码设置的初始化/终止-如果您需要为您的自定义代码分配和释放内存,请将allocate和deallocate插入初始化函数终止函数字段的自定义代码设置,或使用C函数块。

  • 复杂的数据支持金宝app- - -C调用者块在Simulink中不支持复金宝app杂数据类型。金宝app

  • 变量参数- C中不支持变量参数,例如:金宝appInt sprintf(char *str, const char *format,…)

  • c++语法- - -C调用者块不直接支持本机c++语法。金宝app您需要编写一个C函数包装器来与c++代码交互。

测试模型包括C调用者块,看到测试集成C代码(金宝app仿真软件测试)

请注意

如果模型具有自定义代码,则在模型更新或运行后,slprj由于加载了自定义代码模拟可执行文件,文件夹可能被锁定。该文件夹处于锁定状态时,不能被删除。卸载可执行文件并解锁slprj文件夹,使用清晰的墨西哥人命令。看到清晰的

另请参阅

功能

对象

相关的话题