Fuchsia 接口定义语言

Fuchsia 接口定义语言 (FIDL) 是用于描述数据的 Fuchsia 程序使用的进程间通信 (IPC) 协议。FIDL 它提供了一种简化的声明语法,让提供程序可将接口定义为 protocol。支持的数据类型包括整数、浮点数、布尔值、字符串 和 标识名 ,了解所有最新动态。这些函数可以整理成更复杂的数组, 矢量、结构体、表和联合。

请参考以下 Echo 接口的 FIDL 协议示例:

library fuchsia.examples;

const MAX_STRING_LENGTH uint64 = 32;

@discoverable
closed protocol Echo {
    strict EchoString(struct {
        value string:MAX_STRING_LENGTH;
    }) -> (struct {
        response string:MAX_STRING_LENGTH;
    });
    strict SendString(struct {
        value string:MAX_STRING_LENGTH;
    });
    strict -> OnString(struct {
        response string:MAX_STRING_LENGTH;
    });
};

FIDL 协议描述了一组通过通过以下方式发送消息调用的方法: 渠道。通道消息本质上是异步的, 相互独立运行的接收器。FIDL 方法引入了 实现更惯用的客户端编程; 是 FIDL 交易的服务器端。

FIDL 支持以下方法类型:

  • 双向方法:接受可选参数的典型方法调用 返回类型在 -> 运算符后定义的返回类型。双向方法代码块 直到收到响应。在 Echo 示例中,EchoString() 是一种双向方法。
  • 单向方法:立即返回的异步方法调用 而无需等待回复。未声明返回值类型的方法 视为单向传递。在 Echo 示例中,SendString() 方法是一种单向方法。
  • 事件:如有必要,服务器可能会向 称为事件事件会在 -> 运算符。在 Echo 示例中,OnString() 方法是事件。

创建 FIDL 库

FIDL 库将 FIDL 源文件组合在一起。库可充当 其包含的协议的命名空间,而 FIDL 源文件可以隐式 访问同一库中的所有其他声明。FIDL 源文件 import 从其他库导入任何声明。

Fuchsia 构建系统提供 fidl() 构建目标来编译 FIDL 导入一个库库目标的名称必须与 library 声明。请参阅以下 BUILD.gn 示例 对于 fuchsia.examples 库:

# Import the fidl GN template.
import("//build/fidl/fidl.gni")

# Define a FIDL library target.
fidl("fuchsia.examples") {
  # FIDL source files contained in library
  sources = [
    "echo.fidl",
  ]
}
<ph type="x-smartling-placeholder">

在构建时,FIDL 编译器 (fidlc) 前端工具会验证和编译 将库源文件转换为 JSON 中间表示法 (IR)。此 JSON IR 格式是 FIDL 绑定的基础。

生成 FIDL 绑定

组件通过生成的代码使用 FIDL 协议,即 FIDL 绑定。绑定会将请求和响应编码和解码为 FIDL 消息,并通过底层 IPC 通道传输它们。通过 特定于语言的绑定库为这些结构提供了封装容器, 使互动与熟悉的编程习语保持一致。

客户端接口(有时称为代理)执行转换 高级函数调用和 FIDL 消息之间传递的值。在服务器端 绑定会处理传入的请求消息,并通过抽象 接口。

显示 FIDL 绑定如何提供生成的库代码以进行转换的示意图
 函数调用 FIDL 消息,以便跨进程传输
  边界。

在构建时,fidlgen 后端工具会为支持的 fidlc 生成的 JSON IR 库中提供的各种编程语言。例如: fidlgen_rust 会从 JSON IR 生成 Rust 绑定。

fidl() 库目标会为每个容器创建单独的绑定目标 。由于 GN 的性质,系统不会生成这些绑定 除非将其作为依赖项包含在内。

请参阅以下示例 BUILD.gn 代码段,其中包含生成的 fuchsia.examples 库的绑定目标:

Rust

deps = [
  "fidl/fuchsia.examples:fuchsia.examples_rust",
  ...
]

C++

deps = [
  "fidl/fuchsia.examples:fuchsia.examples",
  ...
]

练习:Echo FIDL 库

在本部分中,您将定义一个新的 FIDL 库,其中包含名为 Echo,其中包含将字符串值返回给 调用方。

首先,为 FIDL 库目标创建一个新目录:

mkdir -p vendor/fuchsia-codelab/echo-fidl

在新项目目录中创建以下文件和目录结构:

//vendor/fuchsia-codelab/echo-fidl
                        |- BUILD.gn
                        |- echo.fidl

添加一个名为 echo.fidl 且包含以下内容的新 FIDL 接口文件:

library fidl.examples.routing.echo;

const MAX_STRING_LENGTH uint64 = 64;

@discoverable
closed protocol Echo {
    /// Returns the input.
    strict EchoString(struct {
        value string:<MAX_STRING_LENGTH, optional>;
    }) -> (struct {
        response string:<MAX_STRING_LENGTH, optional>;
    });
};

EchoString 是一种双向方法,接受可选(可为 null)字符串 值,并返回相同的值。

添加包含以下内容的 BUILD.gn 文件,以声明库目标:

import("//build/fidl/fidl.gni")
fidl("echo") {
  name = "fidl.examples.routing.echo"

  sources = [ "echo.fidl" ]

  enable_hlcpp = true
}

将库目标添加到 build 配置:

Rust

fx set workstation_eng.x64 --with vendor/fuchsia-codelab/echo-fidl:echo_rust

C++

fx set workstation_eng.x64 --with vendor/fuchsia-codelab/echo-fidl:echo_hlcpp

检查 FIDL 绑定

fidl() GN 目标会编译 FIDL 接口,并生成额外的 构建目标以提供各种语言的绑定。要检查 因此必须编译各个目标。

编译 fidl.examples.routing.echo 绑定:

Rust

fx build vendor/fuchsia-codelab/echo-fidl:echo_rust

C++

fx build vendor/fuchsia-codelab/echo-fidl:echo_hlcpp

使用 GN 找到为目标生成的源文件,并在 编辑器:

Rust

fx gn desc out/default/ vendor/fuchsia-codelab/echo-fidl:echo_rust.actual sources

C++

fx gn desc out/default/ vendor/fuchsia-codelab/echo-fidl:echo_hlcpp sources

浏览这些文件的内容。下面简要说明了 生成的接口:

Rust

接口 说明
EchoMarker 用于针对给定协议打开代理和请求数据流。
EchoProxy 将协议方法转换为 FIDL 请求的异步客户端 通过 IPC 通道发送的消息。
EchoSynchronousProxy 将协议方法转换为 FIDL 请求的同步客户端 通过 IPC 通道发送的消息。
EchoRequest 用于处理每种协议方法的传入请求的结构化类型。
EchoRequestStream 通过 IPC 通道处理传入的 FIDL 请求消息的流。
EchoEchoStringResponder 用于将每个代理请求的返回值作为 FIDL 响应发送的回调 消息。

C++

接口 说明
EchoPtr 将协议方法转换为 FIDL 请求的异步客户端 通过 IPC 通道发送的消息。
EchoSyncPtr 将协议方法转换为 FIDL 请求的同步客户端 通过 IPC 通道发送的消息。
Echo 用于替换和处理传入 FIDL 的服务器组件的抽象类 请求。
EchoStringCallback 用于以 FIDL 响应形式发送每个请求的返回值的回调 消息。
<ph type="x-smartling-placeholder">