HLCPP 繫結

程式庫

加入程式庫宣告:

library fuchsia.examples;

這個程式庫的所有程式碼都會在 fuchsia::examples 命名空間中產生, 測試 Scaffolding fuchsia::examples::testing

常數

所有常數都會產生為 constexpr。舉例來說, 下列常數:

const BOARD_SIZE uint8 = 9;
const NAME string = "Tic-Tac-Toe";

在標頭檔案中產生如下:

constexpr uint8_t BOARD_SIZE = 9u;
extern const char[] NAME;

FIDL 原始類型和 C++ 類型之間的對應關係列於 內建類型。字串會宣告為constexpr extern const char[] (由標頭檔案定義),並由 .cc 檔案定義。

欄位

本節說明 FIDL 工具鍊如何將 FIDL 類型轉換為原生類型 就是 HLCPP 中的一種類型這些類型可以以會員類型顯示, 新增至通訊協定方法。

內建類型

根據下表,FIDL 類型會轉換為 C++ 類型:

FIDL 類型 HLCPP 類型
bool bool
int8 int8_t
int16 int16_t
int32 int32_t
int64 int64_t
uint8 uint8_t
uint16 uint16_t
uint32 uint32_t
uint64 uint64_t
float32 float
float64 double
array<T, N> std::array
vector<T>:N std::vector
vector<T>:<N, optional> fidl::VectorPtr
string std::string
string:optional fidl::StringPtr
server_end:Pserver_end:<P, optional> fidl::InterfaceRequest
client_end:Pclient_end:<P, optional> fidl::InterfaceHandle
zx.Handlezx.Handle:optional zx::handle
zx.Handle:Szx.Handle:<S, optional> 系統會使用對應的 zx 類型。例如 zx::vmozx::channel

使用者定義的類型

在 HLCPP 中,使用者定義的類型 (位元、列舉、常數、結構體、聯集或資料表) 為 在繫結中使用產生的類別或變數 (請參閱類型 定義)。如果是可為空值的使用者定義類型 T, 會使用對等產生的類型的 unique_ptr

要求、回應和事件參數

每當 FIDL 需要產生單一類型代表 請求、回應或事件 (例如:產生 fpromise::result 相容的結果類型時) 它使用以下規則:

  • 系統會產生多個引數做為參數類型的 std::tuple
  • 單一參數會直接使用參數類型本身。
  • 空白參數組合會以 void 表示。

類型定義

點數

如果是 bits 定義:

type FileMode = strict bits : uint16 {
    READ = 0b001;
    WRITE = 0b010;
    EXECUTE = 0b100;
};

FIDL 工具鍊會使用指定的基礎程式碼產生 C++ enum class 類型,如果未指定,則使用 uint32_t

enum class FileMode : uint16_t {
    READ = 1u;
    WRITE = 2u;
    EXECUTE = 4u;
};

此外,FIDL 會為 FileMode 產生下列方法:

  • 位元運算子:||=&&=^^= 的實作。 和 ~ 運算子都會產生,允許在位元上進行位元運算,例如 mode |= FileMode::EXECUTE

FIDL 也會產生 const static FileMode FileModeMask 變數。這是 包含列舉類別中所有位元的位元遮罩,可用於取得 刪除原始基礎 uint16_t (或任何類型) 中未使用的位元值 bits 採用的必要條件)。在上述範例中,FileModeMask 的值是 0b111

使用範例:

auto flags = fuchsia::examples::FileMode::READ | fuchsia::examples::FileMode::WRITE;
ASSERT_EQ(static_cast<uint16_t>(flags), 0b11);
flags |= fuchsia::examples::FileMode::EXECUTE;
ASSERT_EQ(flags, fuchsia::examples::FileModeMask);

彈性位元

彈性位元會實作為 class (而非 enum class),其中包含下列其他方法:

  • constexpr FileMode():初始化值時,不含 個位元設定。
  • constexpr FileMode(uint16_t):從基礎建構值 原始值,保留所有未知位元成員。
  • constexpr cpp17::optional<FileMode> TryFrom(uint16_t value):建構 即基礎原始值中位元的例項 (如果該值沒有 包含任何未知成員,否則會傳回 cpp17::nullopt
  • constexpr FileMode TruncatingUnknown(uint16_t value):建構執行個體 並清除任何未知成員。
  • constexpr FileMode unknown_bits() const:傳回包含下列內容的位元值: 接收此位元值中的未知成員。
  • constexpr bool has_unknown_bits() const:傳回此值是否包含 找出所有未知位元。
  • explicit constexpr operator uint16_t() const:將位元值轉換回 對應到基礎原始值
  • explicit constexpr operator bool() const:傳回是否已設定任何位元。

產生的類別會包含每個位元成員的靜態號碼,以及 用於位元遮罩這些欄位與 enum class 的成員完全一致 值,並加上取代 FileModeMaskkMask 成員。

  • const static FileMode READ
  • const static FileMode WRITE
  • const static FileMode EXECUTE
  • const static FileMode kMask
,瞭解如何調查及移除這項存取權。

列舉

採用 enum 定義:

type LocationType = strict enum {
    MUSEUM = 1;
    AIRPORT = 2;
    RESTAURANT = 3;
};

FIDL 工具鍊會使用指定的基礎程式碼產生 C++ enum class 類型,如果未指定,則使用 uint32_t

enum class LocationType : uint32_t {
    MUSEUM = 1u;
    AIRPORT = 2u;
    RESTAURANT = 3u;
};

使用範例:

ASSERT_EQ(static_cast<uint32_t>(fuchsia::examples::LocationType::MUSEUM), 1u);

彈性列舉

彈性列舉是以 class (而非 enum class) 的形式實作,其中包含下列方法:

  • constexpr LocationType():預設建構函式,可將列舉初始化為 未指定未知的值
  • constexpr LocationType(uint32_t value):包含 列舉基礎類型的值
  • constexpr bool IsUnknown():傳回列舉值是否為不明值。
  • constexpr static LocationType Unknown():傳回符合以下情況的列舉值 可能會視為不明如果列舉中有加註 [Unknown],則會傳回該成員的值。如果 如果是這類成員,則所傳回列舉成員的基礎值 未指定,
  • explicit constexpr operator int32_t() const:將列舉轉換回其值 基本價值

產生的類別包含每個列舉成員的靜態成員, 保證符合同等值的 enum class 成員 strict 列舉:

  • const static LocationType MUSEUM
  • const static LocationType AIRPORT
  • const static LocationType RESTAURANT

Structs

假設有 struct 宣告:

type Color = struct {
    id uint32;
    @allow_deprecated_struct_defaults
    name string:MAX_STRING_LENGTH = "red";
};

FIDL 工具鍊會產生包含公開成員和方法的 Color 類型。

  • public 位成員:

    • uint32_t id{}:由於沒有預設值,因此這個欄位已初始化為零 或更新提示
    • std::string name = "red"name 的對應欄位。
  • 方法:

    • static inline std::unique_ptr<Color> New():將 unique_ptr 傳回 新Color

Color 的 6 個特別成員 (預設、複製及移動建構函式, 定義者、複製及移動作業) 均默示定義。

Color 也包含下列相關的產生的值:

  • ColorPtrunique_ptr<Color> 的別名。

如果結構體代表 結果

使用範例:

fuchsia::examples::Color default_color;
ASSERT_EQ(default_color.id, 0u);
ASSERT_EQ(default_color.name, "red");

fuchsia::examples::Color blue = {1, "blue"};
ASSERT_EQ(blue.id, 1u);

聯合工會

以聯集定義為例:

type JsonValue = strict union {
    1: int_value int32;
    2: string_value string:MAX_STRING_LENGTH;
};

FIDL 會產生 JsonValue 類別。JsonValue 包含公開標記列舉 代表可能的變化版本

enum Tag : fidl_xunion_tag_t {
  kIntValue = 2,
  kStringValue = 3,
  Invalid = std::numeric_limits<fidl_xunion_tag_t>::max(),
};

Tag 的每個成員都有一個符合其指定 普通 的值 union 定義中。此外還有 Invalid 欄位,這是 用於尚未設定變化版本的 JsonValue 初始值。

JsonValue 提供以下方法:

  • JsonValue():預設建構函式。此代碼的初始時間為 Tag::Invalid,直到 JsonValue 設定為特定變化版本。使用 WithFoo 建構函式 。
  • ~JsonValue():預設解構函式
  • static JsonValue WithIntValue(int32&&)static JsonValue WithStringValue(std::string&&):直接建構 特定版本的聯集。
  • static inline std::unique_ptr<JsonValue> New():將 unique_ptr 傳回 新JsonValue
  • bool has_invalid_tag():如果 JsonValue 的執行個體出現,則傳回 true 則尚未設定變化版本組合在變化版本前,使用者不應存取聯集 設定後,系統會將其視為未定義的行為。
  • bool is_int_value() constbool is_string_value() const:每個變化版本 擁有相關聯的方法,可檢查 JsonValue 的例項是否 該變化版本
  • const int32_t& int_value() constconst std::string& string_value() const:每個變化版本的唯讀存取子方法。如果 「JsonValue」並未提供指定的變化版本集
  • int32_t& int_value()std::string& string_value():可變動的存取子 方法。如果 JsonValue 的變化版本與 這會刪除目前資料並重新初始化 做為指定的變數。
  • JsonValue& set_int_value(int32_t)JsonValue& set_string_value(std::string):每個變化版本的 Setter 方法。
  • Tag Which() const:傳回目前 標記 JsonValue
  • fidl_xunion_tag_t Ordinal() const:傳回原始 fidl_xunion_tag_t 標記。 使用 Which() (除非需要原始序數)

JsonValue 也包含下列相關的產生的值:

  • JsonValuePtrunique_ptr<Foo> 的別名。

如果聯合體能代表 結果

使用範例:

auto int_val = fuchsia::examples::JsonValue::WithIntValue(1);
ASSERT_EQ(int_val.Which(), fuchsia::examples::JsonValue::Tag::kIntValue);
ASSERT_TRUE(int_val.is_int_value());

auto str_val = fuchsia::examples::JsonValue::WithStringValue("1");
ASSERT_EQ(str_val.Which(), fuchsia::examples::JsonValue::Tag::kStringValue);
ASSERT_TRUE(str_val.is_string_value());

fuchsia::examples::JsonValuePtr other_int_val = std::make_unique<fuchsia::examples::JsonValue>();
other_int_val->set_int_value(5);
ASSERT_EQ(other_int_val->int_value(), 5);

彈性聯集和未知的變體

彈性聯集在產生的 Tag 中有額外變化版本 類別:

enum Tag : fidl_xunion_tag_t {
    kUnknown = 0,
    ... // other fields omitted
};

當 FIDL 訊息含有不明變體的聯集時,解碼成 JsonValueJsonValue::Which() 會傳回 JsonValue::Tag::kUnknownJsonValue::Ordinal() 會傳回未知的序數。

彈性的 JsonValue 類型具有與不明互動的額外方法。 取決於資料類型是否為 值或資源類型。值類型不會 參照 zx::handle 的不明資料方法。

「資源」類型的彈性 JsonValue 具有 包含以下額外方法:

  • const vector<uint8_t>* UnknownBytes() const:傳回 聯集變數 (如果不明),否則則為 nullptr
  • const vector<zx::handle>* UnknownHandles() const:傳回 如果類別不明,則為週遊順序中的聯集變體;或 否則為 nullptr
  • JsonValue& SetUnknownData(fidl_xunion_tag_t ordinal, vector<uint8_t> bytes, vector<zx::handle> handles):與已知資料集的 setter 方法類似 成員,這會將聯集設為具有指定序數的未知變數。 和控制代碼此方法僅供測試,例如到 確保程式碼能正確處理未知的資料。

類型的彈性 JsonValue 包含下列內容: 其他方法:

  • const vector<uint8_t>* UnknownBytes() const:傳回 聯集變數 (如果不明),否則則為 nullptr
  • JsonValue& SetUnknownData(fidl_xunion_tag_t ordinal, vector<uint8_t> bytes): 與已知成員的 setter 方法類似,這會將聯集設為 含指定序數和位元組的不明子類。這個方法 用於測試,例如,確保程式碼能處理不明資料 正確。

將含有未知變體的聯集編碼寫入未知的資料,並 再次接上電線

在解碼未知的變體時,Strict 聯集會失敗。 彈性類型的聯集會在發生時失敗 使用控點即可解碼未知的變體。

表格

採用 table 定義:

type User = table {
    1: age uint8;
    2: name string:MAX_STRING_LENGTH;
};

FIDL 工具鍊會使用下列方法產生 User 類別:

  • User():預設建構函式,未設定所有欄位初始化。
  • User(User&&):移動建構函式。
  • ~User():解構。
  • User& User::operator=(User&&):移動作業。
  • bool IsEmpty() const:如果未設定任何欄位,則傳回 true。
  • bool has_age() constbool has_name() const:傳回欄位是否為 設定。
  • const uint8_t& age() constconst std::string& name() const:唯讀 欄位存取子方法。如未設定欄位,這些作業就會失敗。
  • uint8_t* mutable_age()std::string* mutable_name():可變動欄位 存取子方法。如果不設定這個欄位,系統就會建構預設值。 設定並傳回。
  • User& set_age(uint8_t)User& set_name(std::string):欄位 setter。
  • void clear_age()void clear_name():透過下列方式清除欄位值: 呼叫解構函式

User 類別也會提供與不明欄位互動的方法 這取決於類型是值或資源類型。 值類型的資料表不會有不明值 參照 zx::handle 的資料方法,而且無法利用 含有帳號代碼的不明欄位

如果 User 是「資源」類型,則具備下列權限: 方法:

  • const std::map<uint64_t, fidl::UnknownData>>& UnknownData() const:傳回 將序數對應至位元組和控制代碼帳號代碼一定會位於 遍歷順序
  • void SetUnknownDataEntry(uint32_t ordinal, fidl::UnknownData&& data):設定 。這個 方法僅能用於測試,例如檢查作業中是否有 欄位才能正確處理。

如果 User類型,則具備下列方法:

  • const std::map<uint64_t, vector<uint8_t>& UnknownData() const:傳回 將序數對應至位元組
  • void SetUnknownDataEntry(uint32_t ordinal, vector<uint8_t>&& data):設定 未知欄位的位元組 (如果不存在)。這個方法 僅供測試,例如檢查含有不明欄位的資料表 正確處理。

User 也包含下列相關的產生的值:

  • UserPtrunique_ptr<User> 的別名。

使用範例:

fuchsia::examples::User user;
ASSERT_FALSE(user.has_age());
user.set_age(100);
*user.mutable_age() += 100;
ASSERT_EQ(user.age(), 200);
user.clear_age();
ASSERT_TRUE(user.IsEmpty());

內嵌版面配置

產生的 C++ 程式碼會使用 fidlc 保留的名稱,供 內嵌版面配置。

通訊協定

指定通訊協定之後:

closed protocol TicTacToe {
    strict StartGame(struct {
        start_first bool;
    });
    strict MakeMove(struct {
        row uint8;
        col uint8;
    }) -> (struct {
        success bool;
        new_state box<GameState>;
    });
    strict -> OnOpponentMove(struct {
        new_state GameState;
    });
};

FIDL 會產生 TicTacToe 類別,做為互動的進入點 並定義要用於 用戶端將透過 Proxy 向伺服器發出呼叫,並為實作 因此效能相當卓越同步用戶端使用不同的虛擬介面 TicTacToe_Sync

TicTacToe 包含下列成員類型:

  • MakeMoveCallbackOnOpponentMoveCallback:每個回應和事件都有 所產生,代表用於處理回呼的回呼類型的成員類型 回應或事件在上述範例中,MakeMoveCallback 別名 「fit::function<void(bool, std::unique_ptr<GameState>)>」和 OnOpponentMoveCallback別名 fit::function<void(GameState)>

TicTacToe 還有下列純虛擬方法 (對應 通訊協定定義中的方法:

  • virtual void StartGame(bool start_first):為火災而設的純虛擬方法, 忘記通訊協定方法它會採用做為要求參數的引數。
  • virtual void MakeMove(uint8_t row, uint8_t col, MakeMoveCallback callback): 採用兩種通訊協定方法的純虛擬方法。它會以引數形式 ,然後是回應處理常式回呼。

TicTacToe_Sync 具有下列純虛擬方法,對應於 方法部分:

  • virtual zx_status_t StartGame(bool start_first):適用於客戶的純虛擬方法 觸發及清除通訊協定方法它會將要求參數做為引數 並傳回 zx_status_t,代表要求是否已送出
  • virtual zx_status_t MakeMove(uint8_t row, uint8_t col, bool* out_success, std::unique_ptr<GameState>* out_new_state):純虛擬方法,雙向兩種 方法通訊協定。它會將要求參數做為引數,後面接著 每個回應參數的輸出指標。其會傳回 zx_status_t 代表方法呼叫是否成功。

其他程式碼也可能根據 屬性套用於通訊協定或其屬性 方法。

用戶端

FIDL 工具鍊會為呼叫 TicTacToe 伺服器:TicTacToePtr,此為別名 fidl::InterfacePtr<TicTacToe> 代表非同步用戶端,而 TicTacToeSyncPtrfidl::SynchronousInterfacePtr<TicTacToe> 別名 代表同步用戶端

解除參照時,TicTacToePtrTicTacToeSyncPtr 會傳回 Proxy 類別 分別實作 TicTacToeTicTacToe_Sync, 向伺服器發出要求在此範例中,假設有呼叫的 TicTacToePtr async_tictactoe,可以透過呼叫 async_tictactoe->StartGame(start_first)async_tictactoe->MakeMove(row, col, callback)

範例說明如何設定及繫結 InterfacePtr 或 「SynchronousInterfacePtr」也涵蓋了 HLCPP 教學課程

fidl::InterfacePtr 類型為執行緒代管。所有呼叫 這種型別必須使用相同的執行緒。fidl::SynchronousInterfacePtr 類型與執行緒相容此類型的例項繫結後,即可使用 從多個執行緒同時擷取內容fidl::InterfaceHandle 類型可以是 用來在執行緒之間安全地轉移頻道帳號代碼。查看課程 參閱有關這些類型的說明文件

伺服器

實作 FIDL 通訊協定的伺服器需要提供具體 實作 TicTacToe

有關如何設定和繫結伺服器實作的範例,請參閱 HLCPP 教學課程。

活動

用戶端

針對 TicTacToePtr tictactoetictactoe.events() 會傳回 Proxy 類別 包含下列公開成員:

  • OnOpponentMoveCallback OnOpponentMoveOnOpponentMove 事件。

用戶端只需將此類別的成員設為所需項目,即可處理事件 事件處理常式。

詳情請參閱頂層產生的通訊協定代碼 回呼類型。

伺服器

如果是 Binding<TicTacToe> tictactoetictactoe.events() 會傳回虛設常式 類別,包含下列公開成員:

  • void OnOpponentMove(GameState new_state):傳送 OnOpponentMove

這個教學課程包含取得 Binding 的範例。

結果

帶有錯誤類型的方法、彈性方法或具有彈性的方法 錯誤類型:

open protocol TicTacToe {
    strict MakeMove(struct {
      row uint8;
      col uint8;
    }) -> (struct {
      new_state GameState;
    }) error MoveError;

    flexible GetState() -> (struct {
      current_state GameState;
    });

    flexible DryRunMove(struct {
      row uint8;
      col uint8;
    }) -> (struct {
      new_state GameState;
    }) error MoveError;
};

FIDL 會產生程式碼,讓用戶端和伺服器可在以下位置使用 fpromise::result: 取代產生的回應類型。方法是產生結果類別 ,代表可與 fpromise::result 互換的回應。

  • MakeMove
    • 產生類別 TicTacToe_MakeMove_Result
    • 可與「fpromise::result<GameState, MoveError>」互換
  • GetState
    • 產生類別 TicTacToe_GetState_Result
    • 可與「fpromise::result<GameState, fidl::FrameworkErr>」互換
  • DryRunMove

    • 產生類別 TicTacToe_DryRunMove_Result
    • 可互換的 fpromise::result<GameState, std::variant<MoveError, fidl::FrameworkErr>>

    使用這項功能,例如在伺服器端實作這些方法 看起來會像這樣:

void MakeMove(uint8_t row, uint8_t col, MakeMoveCallback callback) override {
  std::optional<MoveError> error = ApplyMove(row, col);
  if (!error.has_value()) {
    callback(fpromise::ok(game_state_.state()));
  }
  callback(fpromise::error(error.value()));
}

void GetState(MakeMoveCallback callback) override {
  callback(fpromise::ok(game_state_.state()));
  // The server application code *must not* attempt to send a
  // fidl::FrameworkErr. If it does, the server binding will panic.
  }

void DryRynMove(uint8_t row, uint8_t col, MakeMoveCallback callback) override {
  std::optional<MoveError> error = TestMove(row, col);
  if (!error.has_value()) {
    callback(fpromise::ok(game_state_.state()));
  }
  // The server application code *must not* attempt to send a
  // fidl::FrameworkErr. If it does, the server binding will panic.
  callback(fpromise::error(error.value()));
}

在用戶端上使用此範例,在非同步案例中會是:

async_game->MakeMove([&](fpromise::result<GameState, MoveError> response) { ... });
async_game->GetState(
    [&](fpromise::result<GameState, fidl::FrameworkErr> response) { ... });
async_game->DryRunMove(
    [&](fpromise::result<GameState, std::variant<MoveError, fidl::FrameworkErr>> response) { ... });

在用戶端上,fidl::FrameworkErr 表示彈性雙向性 伺服器無法識別互動。

產生程式碼時,FIDL 工具鍊會將 TicTacToe_*_Result 視為 union,最多包含三個變化版本:

  • response 是產生的類型,會遵循 參數類型轉換規則
    • 表示 MakeMove 在其結構體傳回類型中傳回單一參數,或者 傳回類型是元組或聯集,傳回類型就會是 fpromise::result<T, ...>,其中 T 是 struct 或 tuple 或 union 傳回型別。
    • 如果 MakeMove 成功傳回多個值,結果類型就會是 回應參數的元組 fpromise::result<std::tuple<...>, ...>
    • 如果 MakeMove 傳回空白回應,結果類型就會是 fpromise::result<void, ...>
  • err 是錯誤類型,在兩個例子中都是 MoveError MakeMoveDryRunMove
    • 只有在方法使用錯誤語法時,才會有這個變數。
  • framework_err 類型一律為 fidl::FrameworkErr
    • 只有方法為 flexible 時,才會有這個變數。

TicTacToe_*_Result 類型提供一般 聯集。此外,TicTacToe_*_Result 類型可提供能夠 允許與 fpromise::result 互通,例如: TicTacToe_MakeMove_Result:

  • TicTacToe_MakeMove_Result(fpromise::result<GameState, MoveError>&& result):移動 來自 fpromise::result 的建構函式。
  • TicTacToe_MakeMove_Result(fpromise::ok_result<GameState>&& result):移動 來自 fpromise::ok_result 的建構函式。
  • TicTacToe_MakeMove_Result(fpromise::error_result<MoveError>&& result):移動 來自 fpromise::error_result 的建構函式。
  • operator fpromise::result<GameState, MoveError>() &&:轉換為 fpromise::result

對於其他類型的轉換,其他 TicTacToe_*_Result 類型會有類似的轉換 對應的 fpromise::result 類型。

FIDL 工具鍊也會產生 TicTacToe_MakeMove_Response 類別, 是 TicTacToe_MakeMove_Resultresponse 變體類型。本課程 會被視為 FIDL 結構,其中包含與 成功的回應除了 regular structTicTacToe_MakeMove_Response 可提供額外的 允許與 std::tuple 互通的方法:

  • explicit TicTacToe_MakeMove_Response(std::tuple<GameState> _value_tuple): 元組的建構函式。
  • operator std::tuple<GameState>() &&:元組的轉換運算子。

不明互動處理

伺服器端

當通訊協定宣告為 openajar (即產生的介面類別) 時, 例如:TicTacToe,其中包含額外的虛擬方法,稱為 handle_unknown_method,當中包含以下簽章:

// If the protocol is open:
virtual void handle_unknown_method(uint64_t ordinal, bool method_has_response) = 0;
// If the protocol is ajar:
virtual void handle_unknown_method(uint64_t ordinal) = 0;

實作 openajar 伺服器時,您必須一併實作 方法。ordinal 參數是該方法的 FIDL 方法序數 。如果通訊協定是 open,則 method_has_response 參數 指出方法為單向或雙向;是一種單向方法 method_has_response 為 false,如果是雙向方法,則為 true。在 ajar 通訊協定,只能處理不明的單向方法。

伺服器收到訊息時,系統就會呼叫 handle_unknown_method 方法 可以處理的未知彈性方法

用戶端

用戶端無法判斷自己是否已知道 flexible 單向方法。 設定要求如果是 flexible 雙向方法,其結果為 聯集可用於判斷方法是否已知 伺服器如果 TicTacToe_<Method>_Resultframework_err 變化版本 類別已設定,或者轉換的 fpromise::result 具有 fidl::FrameworkErr 錯誤設定,表示伺服器無法辨識此方法。

傳送單向方法和接收事件的 API 與 strict 相同 和 flexible 單向方法和事件。

針對 openajar 通訊協定,產生的 TicTacToe_Proxy 類別將有一個額外的公開欄位,稱為 handle_unknown_event,且具有下列類型:

fit::function<void(uint64_t)> handle_unknown_event;

就像針對通訊協定中宣告的事件事件處理常式,例如 OnOpponentMove,您可以在這裡指派要在每次時呼叫的函式回呼 收到未知的 flexible 事件。單一 uint64_t 引數傳遞至 回呼是事件的 FIDL 方法序數。

通訊協定組合

FIDL 沒有繼承的概念,而會產生完整的程式碼做為 以上說明適用於所有編寫的通訊協定。於 也就是程式碼產生的

protocol A {
    Foo();
};

protocol B {
    compose A;
    Bar();
};

提供的 API 與為以下項目產生的程式碼相同:

protocol A {
    Foo();
};

protocol B {
    Foo();
    Bar();
};

產生的程式碼會相同,但方法序數除外。

通訊協定和方法屬性

不透明

適用於附有 @transitional敬上 通訊協定類別上的 virtual 方法並非純粹。這樣一來, 通訊協定類別的實作缺少要編譯的方法覆寫

可供偵測

通訊協定加上 @discoverable敬上 屬性會使 FIDL 工具鍊在通訊協定類別上產生額外的 static const char Name_[] 欄位,其中包含完整的通訊協定名稱。換 程式庫 foo.bar 中的通訊協定 Baz,產生的名稱為 "foo.bar.Baz"

測試施工架

FIDL 工具鍊也會產生後置字串為 _test_base.h 的檔案, 包含用於測試 FIDL 伺服器實作的便利程式碼。這個檔案 包含每個通訊協定的一個類別,而該類別會為每個通訊協定提供虛設常式實作 類別的方法,讓您能只實作 在測試期間使用。這些類別會產生到 testing 命名空間中 新增到產生的程式庫的命名空間中 (例如:程式庫 games.tictactoe,這些類別會產生 games::tictactoe::testing)。

針對上述相同的 TicTacToe 通訊協定,FIDL 工具鍊會產生 子類別 TicTacToeTicTacToe_TestBase 類別 (請參閱 通訊協定),包含下列方法:

  • virtual ~TicTacToe_TestBase() {}:解構。
  • virtual void NotImplemented_(const std::string& name) = 0:純虛擬 方法。

TicTacToe_TestBase 提供虛擬通訊協定方法的實作內容 StartGameMakeMove,為了僅呼叫 NotImplemented_("StartGame")NotImplemented_("MakeMove")

擴充功能

fostr 是獨立的程式庫,提供格式化公用程式 (美化排版) HLCPP 中的 FIDL 類型。你可以在 教學課程