C Function
在模型中使用C代码。
类型: CFunction
图书馆中的路径:
|
资料描述
座 C Function 允许在*Engee*模型中使用c代码和具有C API的共享库。
连接使用内部静态变量的动态库时,应确保它提供了用于初始化/去初始化这些变量的API。 必须在选项卡中调用相应的函数。 起始码 和 终端码,终端码 源代码编辑器。 否则,静态变量将在模拟之间保留其最新值,这可能导致在再次运行模型时产生错误的结果。
|
源代码编辑器
源代码编辑器的工作区由四个选项卡组成:
-
输出码-包含在模型计算的每个步骤中执行的代码; -
起始码-包含在模型初始化期间执行一次的代码; -
终端码,终端码-包含在模型停止时运行一次的代码; -
共享代码-包含允许在块的实例之间交换全局(共享)变量和函数的代码 C Function .
C语言的语法在每个部分中突出显示。
在该部分 输出码 有一个与模拟器和代码生成器相关的特殊注释块。
注释允许您将源代码中的变量与块的信号(输入和输出)相关联。 C Function ,以及指定构建代码所需的附加信息并在模型中使用它。

功能界面提示
以正确访问块的输入、输出、参数和操作变量。 C Function 重要的是要知道这些函数的签名(接口)。 以前,您必须自己弄清楚它的组成,这使得编写代码变得更加困难,并可能导致错误。
现在在块源代码的所有选项卡上 C Function ,除了标签 共享代码 信息*区域显示在编辑器的左下角,其中自动形成并显示函数的界面(原型),对应于块的当前设置(输入,输出,参数和在选项卡上设置的工作变量*Basic,Parameters*和*Work Variables):

这使您不仅可以看到函数的主体,还可以看到它在编写代码时的确切接口,例如:
void CFunction_step(double t, uint32_t in1, double param1, uint32_t *out1);
该提示在块配置更改时动态更新,有助于避免在访问源代码中的输入,输出,参数和工作变量时出错。
从块生成C代码的特点 C Function
座 C Function 支持C代码生成。 在生成代码时,块 C Function 它变成了封装源代码所有四个部分内容的函数。
目前,C代码生成器没有为构建系统提供额外的信息,这些信息将基于块指令。 C Function . 指令在部分中指定 Build options 块设置:

块的重用
标签 共享代码 块的源代码 C Function 允许您设置可用于在块实例之间交换数据和函数的通用代码。 C Function 在参数中具有相同的名称 Function name .
为了使用该功能 共享代码,你需要创建一个块 C Function ,在参数中为其指定一个名称 Function name ,然后将此块保存到 用户库
. 之后,该块可以在几个地方添加到模型中,在那里它将保留对通用数据和函数的访问。 因此,仿真只创建一个共享库和一组函数,供块的所有实例使用。 C Function .
在为参数中具有相同名称的块生成代码时 Function name 只创建常规函数 初始化, 步骤 和 任期,以及标签中的代码 共享代码 它被添加到项目一次。 这简化了代码管理,并提供跨块的所有实例访问共享数据。 C Function .
操作变量
标签 Work Variables 街区 C Function 允许您设置静态工作变量,这些变量保持特定于块的每个实例,即使几个块具有相同的参数值。 Function name . 这些工作变量类似于参数,但在执行期间从块的源代码更改其值的能力不同。 这种方法允许您存储和修改仅在块的特定实例中使用的数据。
对于选项卡上的每个工作变量 Work Variables 指定 Name 和 Size in bytes. 在源代码中,这些变量可以通过指向结构的指针访问。 工作,这是存在于所有三个块函数的接口: 步骤, 初始化,而 任期. 例子::

在这里,对齐在源代码中使用,其中宏 is_对齐 检查变量是否正确对齐。 变量 工作-可变1 和 工作_可变3 在选项卡上预定义 Work Variables 并可通过结构 工作.
使用数组
当数据从Julia转移到C代码时,重要的是要考虑索引和数组结构的差异。 这对于在传输过程中可以转置(重新排列索引的顺序)的多维数组是相关的。 以下是处理数组时要考虑的要点。:
了解有关使用数组的更多信息
-
一维数组-将一维数组从Julia传输到C时,数组保留其结构。 C中的索引从
0因此,在访问数组元素时,必须考虑到这种偏移。 例如,如果block参数 C Function 一维数组写成a=[1, 2, 3],那么在C语言:# include <stdio.h> int main() { int a[3] = {1, 2, 3}; printf("%d", a[2]); // Вывeдet 3 return 0; }在此示例中,要获取具有索引的数组元素的值
2正在使用地址a[2],这将返回值3. -
多维数组-多维数组在从Julia转移到C时可以改变索引的顺序,在C代码中,数组会被转置,这意味着在访问数组元素时,需要考虑改变索引的顺序。 例如,Julia中有一个数组:
a = [1 2 3; 4 5 6] # Julia将其解释为2x3矩阵 2x3 Matrix{Int64} 1 2 3 4 5 6 # 访问数组元素 a [1,2] 2然后在C:
#include <stdio.h> int main() { int a[3][2] = { {1, 4}, {2, 5}, {3, 6} }; printf("%d", a[1][0]); // 产出2 return 0; }阵列
[1 2 3; 4 5 6]在Julia中,它变成了一个数组a[2][3]在C中,其中第一个索引指向一行,第二个指向列。 在此示例中,在C中,要获取具有值的元素2使用索引a[1][0]. 因此,C中的数组实际上存储了转置的Julia数组的元素,在访问元素时必须考虑到这一点。
当使用三维和更复杂的数组时,索引也会发生变化。 例如,如果Julia中的数组具有维度 [2, 3, 4],那么在C中它将表示为 [4][3][2]. 在c代码中访问数组元素时必须考虑到这一点。
Julia中的三维数组示例:
a = reshape(1:24, 2, 3, 4)
[:, :, 1] =
1 3 5
2 4 6
[:, :, 2] =
7 9 11
8 10 12
[:, :, 3] =
13 15 17
14 16 18
[:, :, 4] =
19 21 23
20 22 24
println(a[1, 2, 3]) # 产出13
V s:
#include <stdio.h>
int main() {
int a[4][3][2] = {
{
{1, 4},
{2, 5},
{3, 6}
},
{
{7, 10},
{8, 11},
{9, 12}
},
{
{13, 16},
{14, 17},
{15, 18}
},
{
{19, 22},
{20, 23},
{21, 24}
}
};
printf("%d", a[2][1][0]); // 产出13
return 0;
}
|
将索引从Julia转换为C的一般规则是更改顺序:
这意味着c中的索引以相反的顺序写入。 |
使用轮胎
在街区里 C Function 输入/输出端口和块参数都支持总线操作。 设置和使用轮胎的特征如下所述。:
港口的巴士
要在输入或输出端口上设置总线:
-
在相应端口(*Ports*选项卡)的类型参数中,选择类型
N.公共标志. -
之后,参数*输入总线类型*(或*输出总线类型*)将自动采取形式:
BusSignal((), Tuple{}, ())在这里你应该指定:
-
总线的类型是显式的,例如:
BusSignal((:s1, :s2), (Float64, Int64), ((), ()))哪里
:s1,:s2-信号名称;(Float64,Int64)-他们的基本类型;), (-它们的尺寸。 -
或包含在*Engee*工作区中定义的总线描述的变量的名称(在窗口中 variables)或由C/Julia代码生成。
-
|
如果需要,您可以使用第四个参数指定总线名称。:
N.公共标志:s1,:s2),(Float64,Int64), ((),(,:MyBus).
|
Main
Number of input ports — 输入端口数
+
1(默认)
Details
定义块的输入端口数。 参数值 Number of input ports 它将对应于输入端口的数量。
Number of output ports — 输出端口数
+
1(默认)
Details
定义块的输出端口数。 参数值 Number of output ports 它将对应于输出端口的数量。
Function name — 几个块的通用代码的ID
+
否(默认情况下)
Details
指定字符串值以组合块代码。 C Function . 参数中具有相同名称的块 Function name 他们将使用通用代码并通过源代码选项卡交换数据。 共享代码 街区 C Function .
如果将字段留空,则选择的块 C Function 它将保持脱机状态(默认情况下)。
|
在参数中 Function name 可以指定为绝对路径(从 您也可以只指定文件名:在这种情况下,*Engee*首先在当前目录中搜索文件,然后在 Engee路径编辑器. |
Sample time — 计算步骤之间的间隔
+
-1(默认)
Details
将计算步骤之间的间隔指定为非负数。 要继承计算步骤,请将此参数设置为 −1.
港口
入口
Input port 1 — 1号输入端口
+
标量,标量 | 向量资料 | 矩阵
Details
要操作输入端口,请填写/配置以下字段:
-
*Label*是输入端口的名称(文本标签)。 默认情况下,不填写名称单元格(未指定名称)。
-
*变量名*是源代码C代码中输入端口变量的名称。 默认情况下
输入1./* 在模型计算的每一步调用此代码。 */ output1 = input1 * param1;哪里
输入1-输入端口变量的名称;输出1-输出端口变量的名称;param1-参数变量的名称。 -
类型是c源代码中输入端口变量的数据类型。 变量的数据类型必须与信号的数据类型匹配。 支持基本的C数据类型:
double(默认情况下)|浮子,浮子|int8_t|uint8_t|int16_t|uint16_t|int32_t|uint32_t|int64_tuint64_t|int128_t|uint128_t|布尔|N.公共标志 -
尺寸-输入信号的尺寸
1(默认).*Size*字段使用Julia表示法,其中size写成元组,例如, (2, 3, 4). 但是,在C代码中使用此端口时,有必要考虑到索引顺序的更改。 这意味着,如果端口设置与大小(2, 3, 4),然后在C代码中,变量将具有维度[4][3][2]. 这个规则类似于参数的工作方式:与Julia相比,c中的索引顺序被转置。
出口;出口
Output port 1 — 1号输出端口
+
标量,标量 | 向量资料 | 矩阵
Details
要操作输出端口,请填写/配置以下字段:
-
*Label*是输出端口的名称(文本标签)。 默认情况下,不填写名称单元格(未设置名称)。
-
*变量名*是源代码C代码中输出端口变量的名称。 默认情况下
输出1./* 在模型计算的每一步调用此代码。 */ output1 = input1 * param1;哪里
输出1-输出端口变量的名称;输入1-输入端口变量的名称;param1-参数变量的名称。 -
类型是c源代码中输出端口变量的数据类型。 变量的数据类型必须与信号的数据类型匹配。 支持基本的C数据类型:
double(默认情况下)|浮子,浮子|int8_t|uint8_t|int16_t|uint16_t|int32_t|uint32_t|int64_tuint64_t|int128_t|uint128_t|布尔|N.公共标志 -
尺寸-输出信号的尺寸
1(默认).*Size*字段使用Julia表示法,其中size写成元组,例如, (2, 3, 4). 但是,在C代码中使用此端口时,有必要考虑到索引顺序的更改。 这意味着,如果端口设置与大小(2, 3, 4),然后在C代码中,变量将具有维度[4][3][2]. 这个规则类似于参数的工作方式:与Julia相比,c中的索引顺序被转置。
Parameters
Number of parameters — 指定参数的数量
+
1(默认)
Details
块中使用的参数的数量。
Parameter 1 — 将参数定义为变量
+
1(默认)
Details
将参数定义为要在源代码中使用的变量:
-
Name -默认参数名称
param1. 它是可以改变的。 新参数的名称被调用param2然后上升。 -
Value -参数的默认值
0. 它是可以改变的。 默认情况下,新参数的值也为零。
要使用参数,请转到块代码编辑器。 C Function (编辑源代码)在选项卡中 输出码 并输入所需参数的名称。 默认情况下:
/* 在模型计算的每一步调用此代码。 */
output1 = input1 * param1;
哪里 输入1 -输入信号变量; 输出1 -可变输出信号。
Work Variables
Number of work variables — 工作变量数
+
0(默认)
Details
块中用于存储特定于每个实例的数据的工作变量的数量。 工作变量可通过结构 工作 并且可以在函数中使用 初始化, 步骤 和 任期 用于写入和读取数据。
每个变量都设置有参数 Name 和 Size in bytes ,它允许您存储各种类型的数据。 如果一个变量被分配了更大的大小,那么它可以用作数组。
Work Variable 1 — 定义工作变量
+
1(默认)
Details
定义要在源代码中使用的工作变量:
-
Name -默认参数名称
工作-可变1. 它是可以改变的。 新工作变量的名称被调用工作-可变2然后上升。 -
Size in bytes -为变量分配的内存量,以字节为单位。 此参数允许您指定变量的大小,无论是标量还是数组。
要使变量工作,您需要转到块代码编辑器。 C Function (编辑源代码)在选项卡 输出码 并输入变量名。
构建选项
Source files — 连接源代码文件
+
否(默认情况下)
Details
它用于连接其他源代码文件。 必须包括路径和文件名以及扩展名。 例如:
/user/project/src/example.c
Include directories -确定头文件目录的路径
+
否(默认情况下)
Details
它用于确定包含头文件的目录的路径。 例如:
/user/project/include
Library directories — 确定库目录的路径
+
否(默认情况下)
Details
它用于确定包含共享库的目录的路径。 例如:
/user/project/third_party
Headers — 头文件的连接
+
stdint。h数学。h(默认)
Details
它用于连接头文件。 必须包括头文件的名称以及扩展名。 例如:
example.h
Defines — 附加指令的定义#define
+
否(默认情况下)
Details
用于定义额外的#define指令。 例如:
defines LOWER=0 UPPER=300 STEP=20
Libraries — 连接图书馆
+
否(默认情况下)
Details
它用于连接库。 必须包括库名称和扩展名。 例如:
libexample.so
| 实际的数据类型以及对可能的数据类型的支持取决于块内的用户代码。 |
