Fuchsia 介面定義語言

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 來源檔案必須從其他程式庫import任何宣告。

Fuchsia SDK 提供 fuchsia_fidl_library() 建構目標,可將 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 管道傳輸這些內容。語言專屬的繫結程式庫會為這些結構提供包裝函式,讓您可以符合熟悉的程式設計慣用語。

用戶端介面 (有時稱為 Proxy) 會在較高層級的函式呼叫和 FIDL 訊息之間執行轉譯。在伺服器端,繫結會處理傳入要求訊息,並透過抽象介面傳送這些訊息給要實作的元件。

這張圖表顯示 FIDL 繫結如何提供產生的程式庫程式碼,將函式呼叫轉譯為 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
protocol Echo {
    /// Returns the input.
    EchoString(struct {
        value string:<MAX_STRING_LENGTH, optional>;
    }) -> (struct {
        response string:<MAX_STRING_LENGTH, optional>;
    });
};

EchoString 是一種雙向方法,接受選用 (可為空值) 字串值並傳回相同的值。

新增含有以下內容的 BUILD.bazel 檔案,以宣告程式庫目標:

echo-fidl/BUILD.bazel:

load(
    "@rules_fuchsia//fuchsia:defs.bzl",
    "fuchsia_fidl_llcpp_library",
    "fuchsia_fidl_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 時提供。