程式庫
給定程式庫宣告:
library fuchsia.examples;
這個程式庫的所有程式碼都會在 fuchsia::examples
命名空間中產生,而測試架構則會在 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++ 類型的對應關係,請參閱「內建類型」一文。在標頭檔案中,字串會宣告為 extern const char[]
,而非 constexpr
,並在 .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:P 、server_end:<P, optional> |
fidl::InterfaceRequest |
client_end:P 、client_end:<P, optional> |
fidl::InterfaceHandle |
zx.Handle 、zx.Handle:optional |
zx::handle |
zx.Handle:S 、zx.Handle:<S, optional> |
系統會使用對應的 zx 類型。例如 zx::vmo 或 zx::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
值的成員完全相符,但新增了用來取代 FileModeMask
的 kMask
成員。
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
成員相符:
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
也具有下列相關的產生值:
ColorPtr
:unique_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() const
和bool is_string_value() const
:每個變化版本都有相關聯的方法,可檢查JsonValue
的例項是否屬於該變化版本const int32_t& int_value() const
和const 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
也具有下列相關的產生值:
JsonValuePtr
:unique_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 訊息解碼為 JsonValue
時,JsonValue::Which()
會傳回 JsonValue::Tag::kUnknown
,而 JsonValue::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 方法類似,此方法會將聯集設為使用指定序數和位元的未知變數。這個方法應僅用於測試,例如確保程式碼能正確處理不明資料。
對含有不明變化版本的聯集進行編碼時,系統會將不明資料和原始序數寫回網路。
在解碼不明變數時,嚴格的聯集會失敗。彈性的值類型聯集在解碼使用句柄的不明變數時會失敗。
表格
給定資料表定義:
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() const
和bool has_name() const
:傳回欄位是否已設定。const uint8_t& age() const
和const 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
也具有下列相關的產生值:
UserPtr
:unique_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
類別,做為與通訊協定互動的進入點,並定義用戶端用於將伺服器代理呼叫的服務介面,以及用於實作通訊協定的伺服器介面。同步處理用戶端會使用不同的虛擬介面 TicTacToe_Sync
。
TicTacToe
包含下列成員類型:
MakeMoveCallback
和OnOpponentMoveCallback
:每個回應和事件都會產生一個成員類型,代表用於處理該回應或事件的回呼類型。在上述範例中,MakeMoveCallback
別名為fit::function<void(bool, std::unique_ptr<GameState>)>
,OnOpponentMoveCallback
別名為fit::function<void(GameState)>
。
TicTacToe
還具有下列純虛擬方法,對應於通訊協定定義中的各個方法:
virtual void StartGame(bool start_first)
:用於 fire and forget 通訊協定方法的純虛擬方法。並將要求參數做為引數。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>
,代表非同步用戶端;TicTacToeSyncPtr
,其別名為 fidl::SynchronousInterfacePtr<TicTacToe>
,代表同步用戶端。
解參照時,TicTacToePtr
和 TicTacToeSyncPtr
會傳回代理程式類別,分別實作 TicTacToe
和 TicTacToe_Sync
,這些代理程式會將要求轉送至伺服器。在本例中,假設有一個名為 async_tictactoe
的 TicTacToePtr
,您可以呼叫 async_tictactoe->StartGame(start_first)
或 async_tictactoe->MakeMove(row,
col, callback)
來提出要求。
HLCPP 教學課程會介紹如何設定並將 InterfacePtr
或 SynchronousInterfacePtr
繫結至管道。
fidl::InterfacePtr
類型不支援執行緒。所有對此類型執行個體的呼叫都必須從同一個執行緒發出。fidl::SynchronousInterfacePtr
類型與執行緒相容。一旦此類型例項已繫結,即可同時從多個執行緒使用。fidl::InterfaceHandle
類型可用於在執行緒之間安全地傳輸管道句柄。如需更多詳細資訊,請參閱這些類型的類別說明文件。
伺服器
為 FIDL 通訊協定實作伺服器,需要提供 TicTacToe
的具體實作項目。
HLCPP 教學課程會提供如何設定及繫結伺服器實作項目的範例。
活動
用戶端
針對 TicTacToePtr
tictactoe
,tictactoe.events()
會傳回 Proxy 類別,其中包含下列公開成員:
OnOpponentMoveCallback OnOpponentMove
:OnOpponentMove
事件的回呼處理常式。
用戶端可以將這個類別的會員設為所需的事件處理常式,藉此處理事件。
如要進一步瞭解回呼類型,請參閱頂層產生的通訊協定程式碼。
伺服器
針對 Binding<TicTacToe>
tictactoe
,tictactoe.events()
會傳回包含下列公開成員的 Stub 類別:
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
是結構體的單一參數,或是元組或聯集傳回類型。 - 如果
MakeMove
在成功時傳回多個值,結果類型會是回應參數fpromise::result<std::tuple<...>, ...>
的元組 - 如果
MakeMove
傳回空白回應,結果類型會是fpromise::result<void, ...>
- 如果
err
是錯誤類型,在MakeMove
和DryRunMove
的範例中為MoveError
。- 只有在方法使用錯誤語法時,才會出現這個變化版本。
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_Result
的 response
變化版本類型。這個類別會視為 FIDL 結構體,其中的欄位會對應至成功回應的每個參數。除了可用於一般結構體的方法和成員之外,TicTacToe_MakeMove_Response
還提供其他方法,可與 std::tuple
進行互通作業:
explicit TicTacToe_MakeMove_Response(std::tuple<GameState> _value_tuple)
:從元組建立建構函式。operator std::tuple<GameState>() &&
:元組的轉換運算子。
不明的互動處理
伺服器端
當通訊協定宣告為 open
或 ajar
時,產生的介面類別 (例如 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;
實作 open
或 ajar
伺服器時,您也必須實作這個方法。ordinal
參數是所呼叫方法的 FIDL 方法序號。如果通訊協定為 open
,method_has_response
參數會指出方法是單向還是雙向;對於單向方法,method_has_response
為 false,對於雙向方法,則為 true。在 ajar
通訊協定中,只能處理不明的單向方法。
每當伺服器收到可處理的不明彈性方法時,就會呼叫 handle_unknown_method
方法。
用戶端
用戶端無法判斷伺服器是否知道 flexible
單向方法。針對 flexible
雙向方法,您可以使用結果聯集,判斷伺服器是否知道該方法。如果已設定 TicTacToe_<Method>_Result
類別的 framework_err
變化版本,或是轉換的 fpromise::result
已設定 fidl::FrameworkErr
錯誤,表示伺服器未辨識該方法。
strict
和 flexible
單向方法和事件的 API 相同,可用於傳送單向方法和接收事件。
對於 open
和 ajar
通訊協定,產生的 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 伺服器實作的便利程式碼。這個檔案包含每個通訊協定的類別,為每個類別的方法提供 Stub 實作項目,讓您只實作測試期間使用的各個方法。這些類別會產生至產生程式庫命名空間內的 testing
命名空間 (例如,對於程式庫 games.tictactoe
,這些類別會產生至 games::tictactoe::testing
)。
針對上述相同的 TicTacToe
通訊協定,FIDL 工具鍊會產生 TicTacToe_TestBase
類別,該類別會子類別化 TicTacToe
(請參閱「通訊協定」),提供下列方法:
virtual ~TicTacToe_TestBase() {}
:解構函式。virtual void NotImplemented_(const std::string& name) = 0
:純粹的虛擬方法,會覆寫為未實作的方法定義行為。
TicTacToe_TestBase
為虛擬通訊協定方法 StartGame
和 MakeMove
提供實作方式,這些方法分別實作為呼叫 NotImplemented_("StartGame")
和 NotImplemented_("MakeMove")
。
擴充功能
fostr
是個獨立的程式庫,可提供公用程式,用於在 HLCPP 中設定格式 (漂亮列印) FIDL 類型。如需使用資訊,請參閱教學課程。