QFace IDL 语法

本主题解释了如何使用 QFace 接口定义语言 (IDL)。有关库的完整描述,请参见 https://pelagicore.github.io/qface/

QFace (Qt 接口语言) 是一种接口定义/描述语言 (IDL)。虽然它主要用于在 Qt、QML 和 C++ 之间定义接口,但它足够灵活,可以在其他上下文中使用。

IDL

IDL 使用常用的 API 概念,如模块、接口、属性、结构体、枚举或标志。此外,IDL 了解列表和 模型

  • 列表 - 原始或复杂类型的数组
  • 模型 - 大数据集的容器,通常通过定义的 API 使用
module org.example 1.0

interface Echo {
    string message;
    void echo(string message);
    signal broadcast(string message);
    Status status;
}

enum Status {
    Null, Loading, Ready, Error
}

QFace 提供的数据类型可以分为原始和复杂类型

原始类型

  • bool
  • int
  • real
  • string
  • var

复杂类型

  • 接口
  • 结构体
  • 枚举
  • 标志
  • 数组
  • 模型

该语言本身不提供对映射或字典的支持。QFace 不提供映射容器类型,因为字典中的键需要一个哈希值,这在复杂类型中并不总是可用的。

语法

QFace 的语法定义良好,并基于模块作为信息较大集合的概念。

模块可以包含多个接口、结构体、枚举或标志。

module <module> <version>
import <module> <version>

interface <Identifier> {
    [readonly] <type> <identifier>
    <type> <operation>(<parameter>*)
    signal <signal>(<parameter>*)
}

struct <Identifier> {
    <type> <identifier>;
}

enum <Identifier> {
    <name> = <value>,
}

flag <Identifier> {
    <name> = <value>,
}

QFace 文档始终描述一个模块。每个文档可以包含一个或多个接口、结构体、枚举或标志。每个文档可以使用导入语句导入其他模块。

注意:Qt 接口框架生成器在分析 QFace IDL 文档时存在一些局限性。有关更多信息,请参阅 已知局限性

模块

模块由一个或多个接口、结构体、枚举或标志组成;组合方式多种多样。模块通过其名称进行识别。此名称应是一个 URI,例如,entertainment.tuner

接口

接口是属性、操作和信号的集合。属性携带数据,而操作修改数据。信号用于将更改通知用户。接口是唯一可以包含操作和信号的类型。

interface WeatherStation {
    real temperature;
    void reset();
    signal error(string message);
}

QFace 库不允许扩展接口;这是设计所决定的。

结构体

结构体用作结构化数据的容器。与接口不同,结构体不支持操作和信号。

属性

属性包含关于接口和结构的数据:语法元素允许您描述数据的一些属性。属性可以是IDL中已知的任何类型。它可以标记为readonly,在这种情况下,接口的此属性不应从外部代码写入。但是,由生成器负责强制执行此约束。

枚举或标志

枚举和标志允许您将结构体或接口内部使用的编码信息作为数据类型。枚举和标志是许多流行编程语言中的常见概念。但在IDL中,枚举只能包含单个值,而标志可以通过按位或操作组合多个值。

类型

类型可以是接口、结构体、枚举或标志。类型要么是局部的,要么是外部的。局部类型可以以它们的名称引用。外部类型来自外部模块,并且需要使用它们的完全限定名称进行引用,module.<name>

下面是一个QFace文件的示例。

module entertainment.tuner 1.0;

import common 1.0

interface Tuner {
    // property currentStation
    readonly Station currentStation;
    // operation nextStation
    void nextStation();
    // operation previousStation
    void previousStation();
    // operation updateCurrentStation
    void updateCurrentStation(int stationId);

    list<int> primitiveList;
    list<Station> complexList;
    model<int> primitiveModel;
    model<Station> complexModel;
}

注意:Qt 接口框架生成器在分析 QFace IDL 文档时存在一些局限性。有关更多信息,请参阅 已知局限性

注解

注解是一种向接口定义添加元信息的方法,例如标签。它们应用于接口中的每个符号。

模块、接口、结构体或枚举可以由一个或多个注解引导。您还可以在操作、属性或信号之前使用注解。最终,您可以在允许文档注释的任何位置使用注解。

注解按以下方式编写

@service: {port: 12345}
interface Tuner {
}

代码中的注解在符号之前,并以@标志开始。一个符号可以有多条注解行,每行包含一个单独的注解。内容是YAML格式。收集并使用YAML解析器评估一个符号之前的所有@符号。

对于较大的注解,您可以使用外部注解文档功能。

@singleton: yes
@data: [1,2,3]
@config: { values: [LEFT, RIGHT, TOP] }

这会导致以下YAML内容

singleton: yes
data: [1,2,3]
config: { values: [LEFT, RIGHT, TOP] }

结果,作为一个Python对象,将是

{
  "data": [ 1, 2, 3 ],
  "singleton": true,
  "config": {
    "values": [ "LEFT", "RIGHT", "TOP" ]
  }
}

注解文档

QFace还允许您使用YAML语法在外部文档中指定这些注解。为此,您需要创建一个与QFace文档同名的文档,但扩展名为.yaml

您的文档应类似于以下内容

com.pelagicore.if.Tuner:
    service:
      port: 12345

根级别应包含符号的完全限定名称。查找此符号,然后将与之相关的注解信息与QFace文档中现有的任何注解合并。

合并注解

外部注解在每个符号上覆盖嵌入式注解;字典也会合并。如果合并无法进行,则基于外部文档的注解始终覆盖嵌入式注解。

在导航域模型时,外部注解将放置在较后的部分。

{% if "service" in interface.tags %}
interface {{interface}} is served on port: {{interface.tags.service.port}}
{% else %}
interface {{interface}} is not served
{% endif %}

注意: QFace不指定特定的注解,但仅定义注解格式。定义并记录支持注解集的是生成器。

域模型

通过解析IDL文档创建,域模型对象作为结果。域模型定义了我们系统的结构为对象。它由解析器构建,并作为生成器的输入。

IDL被转换为一个内存中的域模型(请参阅qface/idl/domain.py)。

- System
    - Module
        - Import
        - Interface
              - Property
              - Operation
              - Event
        - Enum
        - Flag
        - Struct
              - Property

域模型是任何代码生成的基。您遍历域树,然后触发自己的代码生成。

© 2024 Qt公司有限公司。此处包含的文档贡献是各自所有者的版权。提供的文档是在自由软件基金会的规则下,依据GNU自由文档许可协议版本1.3的条款授权使用的。Qt及其相关标志是Qt公司在芬兰及/或全球其他国家的商标。