Fuchsia 接口定义语言 (FIDL) 是用于描述数据的 Fuchsia 程序使用的进程间通信 (IPC) 协议。FIDL 提供了一种简化的声明语法,供提供方将接口定义为协议。支持的数据类型包括整数、浮点数、布尔值、字符串和 这些可以整理成更复杂的数组、矢量、结构体、表和联合体。
请考虑以下 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 源文件必须导入其他库中的所有声明。
Fuchsia SDK 提供了 fuchsia_fidl_library()
build 目标,用于将 FIDL 源文件编译为库。库目标的名称必须与每个源文件中的 library
声明一致。请参阅 fuchsia.examples
库的以下 BUILD.bazel
示例:
# Import the fidl template.
load("fuchsia_fidl_library")
# Define a FIDL library target.
fuchsia_fidl_library(
name = "fuchsia.examples",
srcs = [
"echo.fidl",
],
library = ""fuchsia.examples"",
visibility = ["//visibility:public"],
)
在构建时,FIDL 编译器 (fidlc
) 前端工具会验证和编译
将库源文件转换为 JSON 中间表示法 (IR)。这种 JSON IR 格式是 FIDL 绑定的依据。
生成 FIDL 绑定
组件通过称为 FIDL 绑定的生成代码使用 FIDL 协议。绑定会对请求和响应进行编码和解码, FIDL 消息,并通过底层 IPC 通道传输它们。特定于语言的绑定库会围绕这些结构提供封装容器,以便与熟悉的编程惯用法保持一致。
客户端接口(有时称为代理)会在更高级别的函数调用和 FIDL 消息之间执行转换。在服务器端,绑定会处理传入的请求消息,并通过抽象接口将其传递给组件以供实现。
在构建时,fidlgen
后端工具会为支持的
fidlc
生成的 JSON IR 库中提供的各种编程语言。
Fuchsia SDK 提供了构建模板,用于为每个受支持的语言生成绑定。请参阅以下 BUILD.bazel
示例,为 fuchsia.examples
库生成 HLCPP 绑定:
fuchsia_fidl_hlcpp_library(
name = "fuchsia.examples.fidl_cc",
library = ":fuchsia.examples",
visibility = ["//visibility:public"],
deps = [
"@fuchsia_sdk//pkg/fidl_cpp",
],
)
使用此库的组件可以将绑定目标用作依赖项。
练习:Echo FIDL 库
在本部分中,您将定义一个新的 FIDL 库,其中包含一个名为 Echo
的协议,该协议包含一个方法,用于将字符串值返回给调用方。
创建 FIDL 库
首先,为 FIDL 库目标创建一个新目录:
mkdir -p fuchsia-codelab/echo-fidl
完成本部分后,项目应具有以下目录结构:
//fuchsia-codelab/echo-fidl
|- BUILD.bazel
|- echo.fidl
添加一个名为 echo.fidl
且包含以下内容的新 FIDL 接口文件:
echo-fidl/echo.fidl
:
library examples.routing.echo;
const MAX_STRING_LENGTH uint64 = 32;
@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.bazel
文件,以声明库
目标:
echo-fidl/BUILD.bazel
:
load(
"@fuchsia_sdk//fuchsia:defs.bzl",
"fuchsia_fidl_library",
"fuchsia_fidl_llcpp_library",
)
package(default_visibility = ["//visibility:public"])
fuchsia_fidl_library(
name = "examples.routing.echo",
srcs = [
"echo.fidl",
],
library = "examples.routing.echo",
)
fuchsia_fidl_llcpp_library(
name = "examples.routing.echo.fidl_cc",
library = ":examples.routing.echo",
deps = [
"@fuchsia_sdk//pkg/fidl_cpp_v2",
],
)
运行 bazel build
并验证构建是否成功完成:
bazel build --config=fuchsia_x64 //fuchsia-codelab/echo-fidl:examples.routing.echo.fidl_cc
检查 FIDL 绑定
FIDL 绑定目标会编译 FIDL 接口,并生成
bazel-bin/
目录中特定于语言的绑定:
bazel-bin/fuchsia-codelab/echo-fidl/_virtual_includes/
找到并打开上述目录中生成的头文件:
find bazel-bin/fuchsia-codelab/echo-fidl/_virtual_includes -name *.h
浏览这些文件的内容。下面总结了一些生成的关键接口:
接口 | 说明 |
---|---|
Echo
|
表示 FIDL 协议,并充当类型和 类。 |
EchoString
|
FIDL 协议方法的表示形式,供客户端和服务器用来 提供输入的请求和响应 |
fidl::Server<Echo>
|
服务器组件的抽象类,用于替换和处理传入的 FIDL 请求。 |
fidl::internal::NaturalClientImpl<Echo>
|
异步客户端,用于将协议方法转换为通过 IPC 通道发送的 FIDL 请求消息。为此协议创建 fidl::Client 时提供。
|
fidl::internal::NaturalSyncClientImpl<Echo>
|
同步客户端,用于将协议方法转换为通过 IPC 通道发送的 FIDL 请求消息。为此协议创建 fidl::SyncClient 时提供。
|