IDL - 接口定义和语言映射¶
本文描述了使用接口定义语言(IDL)的一个子集来定义组件之间的接口。
作者:Dirk Thomas¶
撰写日期:2019-03¶
最后修改:2020-07¶
范围¶
本文确定了可以使用的接口定义语言(IDL)的一个子集,用于描述组件之间的接口。进一步描述了如何使用这些接口在C、C++和Python中生成代码。
支持的IDL子集¶
ROS 2支持OMG IDL 4.2规范的一个子集。下面未列出的内容可能目前不支持(例如 enums)。
词法约定¶
7.2.2 注释¶
支持行注释(//)以及块注释(/* ... */)。
7.2.3 标识符¶
标识符必须以ASCII字母字符开始,后跟任意数量的ASCII字母字符、数字和下划线( _)字符。
7.2.6 字面量¶
支持以下所有字面量:
整数
字符
字符串
浮点数
定点数
预处理¶
目前,在读取.idl文件时没有进行预处理。
构建块¶
7.4.6.4.1.4 导入¶
必须使用导入来引用声明了在此.idl文件中使用的其他.idl文件中的数据类型。
7.4.1.4.2 模块¶
每个模块必须包含至少一个定义,它们可以嵌套。对于ROS接口,第一级模块通常代表包名,第二级模块区分接口类型(msg, srv, action)。
7.4.1.4.3 常量¶
7.4.1.4.4.4.1 结构体¶
结构体必须至少包含一个成员。
基本类型¶
7.4.1.4.4.2.1 整数类型¶
IDL类型 | 值范围 — | — short | -2^15 … 2^15 - 1 unsigned short | 0 … 2^16 - 1 long | -2^31 … 2^31 - 1 unsigned long | 0 … 2^32 - 1 long long | -2^63 … 2^63 - 1 unsigned long long | 0 … 2^64 - 1
7.4.1.4.4.2.2 浮点数类型¶
IDL类型 | 格式 — | — float | IEEE单精度浮点数 double | IEEE双精度浮点数 long double | IEEE扩展双精度浮点数
7.4.1.4.4.2.3 字符类型¶
IDL类型 | 值范围 — | — char | 8位单字节字符,数值介于0和255之间(见7.2.6.2.1) 该类型可以存储任何字节导向的代码集的单字节字符,或者在数组中使用时,可以编码多字节代码集的多字节字符。
7.4.1.4.4.2.4 宽字符类型¶
IDL类型 | 值范围 — | — wchar | 16位宽字符 虽然IDL规范仅将wchar的大小定义为实现依赖,但DDS-XTypes规范1.2将其定义为16位。
7.4.1.4.4.2.5 布尔类型¶
IDL类型 | 值范围 — | — boolean | TRUE或FALSE中的一个值
7.4.1.4.4.2.6 八位类型¶
IDL类型 | 值范围 — | — octet | 不透明的8位
7.4.13.4.4 8位整数¶
IDL类型 | 值范围 — | — int8 | -2^7 … 2^7 - 1 uint8 | 0 … 2^8 - 1
7.4.13.4.5 显式命名的整数类型¶
IDL类型 | 等效IDL类型 — | — int16 | short uint16 | unsigned short int32 | long uint32 | unsigned long int64 | long long uint64 | unsigned long long
模板类型¶
7.4.1.4.4.3.1 序列¶
| IDL类型 | 值范围 |
| ———————- | —————————————- |
| sequence<type_spec> | 特定type_spec的项目的序列序列是无界的,没有指定最大大小 |
| sequence<type_spec, N> | 指定type_spec的最多N个项目的序列
序列是有界的,包含0到N个项目 |
7.4.1.4.4.3.2 字符串¶
IDL类型 | 值范围 — | — string | 除了空值之外的char序列
7.4.1.4.4.3.3 宽字符串¶
IDL类型 | 值范围 — | — wstring | 除了空值之外的wchar序列
构造类型¶
7.4.1.4.4.4.1 结构体¶
结构体是至少一个成员的组合。
7.4.1.4.4.4.3 枚举¶
枚举类型由有序的枚举器列表组成。
7.4.1.4.4.5 数组¶
通过每个项目的类型和每个维度的显式大小定义多维、固定大小的数组。目前只支持一维、固定大小的数组。
注解¶
支持任意注解的语法。每种注解类型的处理方式取决于下文描述的代码生成。
代码生成¶
待办事项:所有这些
约束检查¶
只有当消息被发布时,才保证生成的消息代码强制执行约束。例如,当一个字段被限制为固定大小的数组时,分配一个错误大小的数组可能不会出错。这可能因客户端库的实现、语言特性和性能成本而在不同客户端库之间不一致。将来,任何客户端库都可能在字段设置或修改时添加额外的约束检查。使用生成的消息代码的用户应假设约束可能随时被强制执行,以适应此类更改。
类型映射¶
下表定义了IDL类型如何映射到以下编程语言:
C11 (或更高)
C++11 (或更高)
Python 3 (或更高)
| IDL类型 | C11 | Python 3 | C++11 |
|---|---|---|---|
| float | float | float | float |
| double | double | float | double |
| long double | long double | float | long double |
| char | unsigned char | str with length 1 | unsigned char |
| wchar | char16_t | str with length 1 | char16_t |
| boolean | _Bool | bool | bool |
| octet | unsigned char | bytes with length 1 | std::byte |
| int8 | int8_t | int | int8_t |
| uint8 | uint8_t | int | uint8_t |
| int16 | int16_t | int | int16_t |
| uint16 | uint16_t | int | uint16_t |
| int32 | int32_t | int | int32_t |
| uint32 | uint32_t | int | uint32_t |
| int64 | int64_t | int | int64_t |
| uint64 | uint64_t | int | uint64_t |
如果std::byte不可用,则使用unsigned char代替。
用户应研究他们选择的中间件和平台对long double的支持。例如,在使用Visual Studio时,它只有64位。
下表定义了IDL模板和构造类型如何映射到编程语言(除非下面另有说明)。当指定T是上述类型之一或IDL结构体时。N是有界类型的上限。
| IDL类型 | C类型 | C++类型 | Python类型 |
|---|---|---|---|
| T[N] | T[N] | std::array |
list |
| sequence |
struct {size_t, T * } | std::vector |
list |
| sequence |
struct {size_t, T * }, size_t N | std::vector |
list |
| string | char * | std::string | str |
| string |
char * | std::string | str |
| wstring | char16_t * | std::u16string | str |
| wstring |
char16_t * | std::u16string | str |
以下这些数组列表有特殊的映射关系, 如果单元格为空,则使用默认映射。
| IDL类型 | C类型 | C++类型 | Python类型 |
|---|---|---|---|
| T[N] | 对于数值类型 T: float, double, int8, uint8, int16, uint16, int32, uint32, int64, uint64 |
- | - |
| sequence sequence |
对于数值类型 T: float, double, int8, uint8, int16, uint16, int32, uint32, int64, uint64 |
- | - |
| octet[N] | - | - | bytes |
| sequence |
- | - | bytes |
| sequence |
- | - | bytes |
标准化注释¶
8.3.2.1 @key 注释¶
ROS 2 节点通过主题交换某个现实世界对象的信息。每个主题中的消息被称为数据样本,代表对象状态的更新。
主题实例是一种通过同一资源(即主题)复用传输多个相同逻辑类型对象更新的方式。在带键的主题中,每条消息都与一个主题实例相关联,每个主题实例都由一个唯一键标识。从这个意义上说,键可以被视为数据库的主键。此键允许节点更新相同类型的不同状态。因此,所有共享相同键值的数据样本都引用相同的对象。
@key 注释允许指示数据成员是键的一部分,可以有零个或多个键字段,并且可以应用于各种类型的结构字段。以下示例展示了如何使用 IDL 格式定义带键的消息:
# KeyedMsgName.idl
module package_name {
module msg {
struct KeyedMsgName {
@key long member1;
string member2;
};
};
};
目前,支持 @key 注释的消息接口格式是 .idl。因此,.msg 和 .srv 尚不支持 @key 注释。有关它们之间等效性和转换的更多信息,请参阅转换为 IDL。
包括原始类型、序列、字符串和结构在内的通用 idl 类型可以被注释为键。以下是一些示例:
| 类型 | 键成员 |
|---|---|
| struct NoKey | boolean member1; long member2; long member3; |
| struct SimpleKey | @key long member1; long member2; |
| struct ArrayKey | @key long member1[3]; |
| struct StringKey | @key string member1; long member2 |
| struct NestedNoKey | SimpleKey member1; long member2; |
| struct NestedKey | @key SimpleKey member1; long member2; |
| struct NestedKey2 | @key NoKey member1; long member2; |
| struct ComplexNestedKey | @key NestedNoKey member1; long member2; |
8.3.3.1 @default 注释¶
默认值用于初始化结构成员。
8.3.5.1 @verbatim 注释¶
当值注释作为语言参数传递时,文本参数被用作所有支持的编程语言中注释元素的 docblock。
复制再试一次分享