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 建構系統提供 fidl() 建構目標,可將 FIDL 來源檔案編譯至程式庫。程式庫目標的名稱必須符合每個來源檔案中的 library 宣告。請參閱下列 fuchsia.examples 程式庫的 BUILD.gn 範例:

# 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",
  ]
}

在建構期間,FIDL 編譯器 (fidlc) 前端工具會驗證程式庫來源檔案,並將其編譯為 JSON 中繼表示法 (IR)。這種 JSON IR 格式是 FIDL 繫結的基礎。

產生 FIDL 繫結

元件會透過產生的程式碼 (稱為 FIDL 繫結) 使用 FIDL 通訊協定。繫結會將要求和回應編碼及解碼為 FIDL 訊息,並透過基礎的 IPC 管道轉移。語言專屬的繫結程式庫為這些結構提供包裝函式,以與熟悉的程式設計語言組合保持一致的互動。

用戶端介面 (有時稱為 Proxy) 會在較高層級的函式呼叫與 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 程式庫

在本節中,您將使用名為 Echo 的通訊協定定義新的 FIDL 程式庫,其中包含單一方法,將字串值傳回至呼叫端。

請先為 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 是一種雙向方法,可接受選用 (可為空值) 字串值並傳回相同的值。

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

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

  sources = [ "echo.fidl" ]

  enable_hlcpp = true
}

將程式庫目標新增至建構設定:

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 用於開啟特定通訊協定的 Proxy 和要求串流。
EchoProxy 這個非同步用戶端可轉換通訊協定方法,轉換成透過 IPC 管道傳送的 FIDL 要求訊息。
EchoSynchronousProxy 同步用戶端,可將通訊協定方法轉換為透過 IPC 管道傳送的 FIDL 要求訊息。
EchoRequest 用於處理各種通訊協定方法傳入要求的結構化類型。
EchoRequestStream 串流處理透過 IPC 管道傳入的 FIDL 要求訊息。
EchoEchoStringResponder 各個 Proxy 要求傳回值的回呼,做為 FIDL 回應訊息。

C++

介面 說明
EchoPtr 這個非同步用戶端可轉換通訊協定方法,轉換成透過 IPC 管道傳送的 FIDL 要求訊息。
EchoSyncPtr 同步用戶端,可將通訊協定方法轉換為透過 IPC 管道傳送的 FIDL 要求訊息。
Echo 伺服器元件的抽象類別,用於覆寫及處理傳入的 FIDL 要求。
EchoStringCallback 針對每個要求,以 FIDL 回應訊息傳送傳回值的回呼。