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

复杂类型

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

该语言本身不提供对映射或字典的支持。《a href="ivigenerator.html">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 Ivi生成器解析QFace IDL文件时有一些局限性。有关更多信息,请参阅已知局限性

模块

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

接口

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

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

QFace库不允许扩展接口;这是按设计。

结构体

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

属性

属性携带接口和结构的数据:语法元素允许您描述一些数据属性。属性可以是IDL conhecido de qualquer tipo.它可以标记为只读,在这种情况下,该接口的此属性不应从外部代码写入。但是,是否实施此约束由生成器决定。

枚举或标识

枚举和标识允许您将结构或接口内部使用的类型信息编码为数据类型。枚举和标识是许多流行编程语言中常见的概念。但在IDL中,枚举只能接收单个值,而标识可以接收多个值的组合,这些值与位或运算符组合。

类型

类型可以是接口、结构体、枚举或标识。类型要么是局部的,要么是外部的。局部类型可以通过其名称进行引用。外部类型来自外部模块,需要使用其完全限定名称模块.<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 Ivi生成器解析QFace IDL文件时有一些局限性。有关更多信息,请参阅已知局限性

注解

注解是向接口定义添加元信息的方式,例如标签。它们对接口中的每个符号都可用。

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

注解的编写方式如下

@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" ]
  }
}

注解文档

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

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

com.pelagicore.ivi.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

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

©2020 年 Qt 公司有限公司。本文件中包含的文档贡献均为各自所有者的版权。提供的文档受 GNU 自由文档许可版1.3 的条件许可,该许可由自由软件基金会发布。Qt 及其相关标志是芬兰和/或其他国家/地区的 Qt 公司的商标。所有其他商标均为各自所有者的财产。