快速參考
以下說明如何判斷 C++ 程式碼中的特定類型/函式/識別符是否屬於新的 C++ 繫結或高階 C++ 繫結。
以 examples.keyvaluestore.baseline
程式庫為例:
library examples.keyvaluestore.baseline;
type Item = struct {
key string:128;
value vector<byte>:64000;
};
type WriteError = flexible enum {
UNKNOWN = 0;
INVALID_KEY = 1;
INVALID_VALUE = 2;
ALREADY_EXISTS = 3;
};
@discoverable
open protocol Store {
/// Writes an item to the store.
flexible WriteItem(struct {
attempt Item;
}) -> () error WriteError;
};
以下說明各種 FIDL 元素在 C++ 繫結中如何對應。請注意,表格中的「C++」是指新的 C++ 繫結,同樣適用於自然網域物件和線路網域物件。「Natural」是指新 C++ 繫結中的自然網域物件。「Wire」是指新 C++ 繫結中的線路網域物件。
FIDL 元素 | C++ 自然類型 | 留言 | |
---|---|---|---|
標頭包含 | C++ | #include <fidl/examples.keyvaluestore.baseline/cpp/fidl.h> | 格式為 `fidl/library name/cpp/fidl.h` |
HLCPP | #include <examples/keyvaluestore/baseline/cpp/fidl.h> | 格式為「以斜線分隔的程式庫名稱/cpp/fidl.h」 | |
程式庫 | C++ | ::examples_keyvaluestore_baseline | New C++ 使用單一層級命名空間。 HLCPP 使用巢狀命名空間。 |
HLCPP | ::examples::keyvaluestore::baseline | ||
項目結構體 | 自然 | ::examples_keyvaluestore_baseline::Item | 除了命名空間差異之外,線路類型會在「::wire」下方巢狀排列。 |
電線 | ::examples_keyvaluestore_baseline::wire::Item | ||
HLCPP | ::examples::keyvaluestore::baseline::Item | ||
WriteError 列舉 | 自然 | ::examples_keyvaluestore_baseline::WriteError | 除了命名空間差異之外,線路類型會在「::wire」下方巢狀。 就列舉和位元而言,線路類型和自然類型是等同的。只是多了一個型別別名。 |
電線 | ::examples_keyvaluestore_baseline::wire::WriteError | ||
HLCPP | ::examples::keyvaluestore::baseline::WriteError | ||
string:128 | 自然 | std::string | |
電線 | fidl::StringView | ||
HLCPP | std::string | ||
vector<byte>:64000 | 自然 | std::vector<uint8_t> | |
電線 | fidl::VectorView<uint8_t> | ||
HLCPP | std::vector<uint8_t> | ||
通訊協定儲存庫 | C++ | ::examples_keyvaluestore_baseline::Store | 標記類型,可攜帶一些關於通訊協定資訊 |
HLCPP | ::examples::keyvaluestore::baseline::Store | 包含通訊協定中方法的抽象基本類別 | |
client_end:Store | C++ | fidl::ClientEnd<Store> | |
HLCPP | fidl::InterfaceHandle<Store> | ||
server_end:Store | C++ | fidl::ServerEnd<Store> | |
HLCPP | fidl::InterfaceRequest<Store> | ||
Store 通訊協定的用戶端和伺服器類型 |
自然 | 用戶端:fidl::Client<Store> 同步用戶端:fidl::SyncClient<Store> 伺服器介面:fidl::Server<Store> 事件處理常式介面:fidl::EventHandler<Store> |
|
電線 | 用戶端:fidl::WireClient<Store> 同步用戶端:fidl::WireSyncClient<Store> 伺服器介面:fidl::WireServer<Store> 事件處理常式介面:fidl::WireEventHandler<Store> |
||
HLCPP | 用戶端:fidl::InterfacePtr<Store> 同步用戶端:fidl::SynchronousInterfacePtr<Store> 伺服器介面:Store 事件處理常式介面:不適用。InterfacePtr 具有 setter,可為每個事件宣告使用一個回呼。 |
以下是設定用戶端最常見的方式:
C++ (自然)
// Connect to the protocol inside the component's namespace. This can fail so it's wrapped in a // |zx::result| and it must be checked for errors. zx::result client_end = component::Connect<examples_canvas_baseline::Instance>(); if (!client_end.is_ok()) { FX_LOGS(ERROR) << "Synchronous error when connecting to the |Instance| protocol: " << client_end.status_string(); return -1; } // Create an instance of the event handler. EventHandler event_handler(loop); // Create an asynchronous client using the newly-established connection. fidl::Client client(std::move(*client_end), dispatcher, &event_handler); FX_LOGS(INFO) << "Outgoing connection enabled";
C++ (Wire)
// Connect to the protocol inside the component's namespace. This can fail so it's wrapped in a // |zx::result| and it must be checked for errors. zx::result client_end = component::Connect<examples_canvas_baseline::Instance>(); if (!client_end.is_ok()) { FX_LOGS(ERROR) << "Synchronous error when connecting to the |Instance| protocol: " << client_end.status_string(); return -1; } // Create an instance of the event handler. EventHandler event_handler(loop); // Create an asynchronous client using the newly-established connection. fidl::WireClient client(std::move(*client_end), dispatcher, &event_handler); FX_LOGS(INFO) << "Outgoing connection enabled";
請參閱畫布範例,查看完整程式碼清單和說明。
以下是實作伺服器最常見的方式:
C++ (自然)
// An implementation of the |Instance| protocol. class InstanceImpl final : public fidl::Server<examples_canvas_baseline::Instance> { void AddLine(AddLineRequest& request, AddLineCompleter::Sync& completer) override { // ... } };
C++ (Wire)
// An implementation of the |Instance| protocol. class InstanceImpl final : public fidl::WireServer<examples_canvas_baseline::Instance> { void AddLine(AddLineRequestView request, AddLineCompleter::Sync& completer) override { // ... } };
請參閱畫布範例,查看完整程式碼清單和說明。
新的 C++ 繫結
新的 C++ 繫結可提供兩種產生的網域物件系列,以及相應的用戶端和伺服器 API,因此可支援低階和高階用途。
自然類型
- 經過最佳化,可滿足高階服務程式設計的需求。
- 使用慣用 C++ 類型 (例如
std::vector
、std::optional
和std::string
) 表示資料結構。 - 使用智慧型指標管理堆積分配的物件。
- 使用
zx::handle
管理句柄擁有權。 - 可在線路 (例如
fidl::StringView
) 和自然類型表示法 (例如std::string
) 之間轉換資料。
線路類型
- 經過最佳化處理,可滿足低階系統程式設計的需求,同時提供比 C 繫結功能更安全的功能。
- 代表記憶體配置與線路格式相符的資料結構,也就是符合 C++ 標準配置。這會開啟原地編碼和解碼的門戶。
- 產生的結構體是底層緩衝區的檢視畫面,不具備記憶體。
- 支援 FIDL 訊息的當地存取功能。
- 提供精細的記憶體配置控管機制。
- 使用自有帳號類型,例如
zx::handle
。請注意,由於產生的結構體是底層緩衝區的檢視畫面,因此父項結構體只有在擁有底層緩衝區時,才會擁有子項句柄。舉例來說,FIDL 結構體會擁有內嵌儲存的所有句柄,但包含句柄的結構體 FIDL 向量會以向量檢視畫面表示,不會擁有離線句柄。
用戶端和伺服器 API
- 與 C 繫結相比,程式碼產生器會產生更多程式碼。這包括建構函式、解構函式、複製/移動函式、網域物件系列之間的轉換、通訊協定用戶端實作項目,以及純虛擬伺服器介面。
- 使用者可透過子類別化提供的伺服器介面,並覆寫每個作業的純虛擬方法,實作伺服器。
- 支援同步和非同步呼叫,以及同步和非同步事件處理的用戶端。
- 需要 C++17 以上版本。
請參閱新版 C++ 教學課程,瞭解如何開始使用。
高階 C++ 繫結
- 經過最佳化,可滿足高階服務程式設計的需求。
- 使用慣用 C++ 類型 (例如
std::vector
、std::optional
和std::string
) 表示資料結構。 - 使用智慧指標管理堆積分配的物件。
- 使用
zx::handle
(libzx) 管理句柄擁有權。 - 可將資料從原地 FIDL 緩衝區轉換為慣用堆積分配的物件。
- 可將資料從慣用堆積分配物件 (例如
std::string
) 轉換為原地緩衝區 (例如fidl::StringView
)。 - 與 C 繫結相比,程式碼產生器會產生更多程式碼。這包括建構函式、解構函式、通訊協定 Proxy、通訊協定 Stub、複製/移動函式,以及從/至原地緩衝區的轉換。
- 用戶端會透過子類別化提供的存根目錄,並為每個作業實作虛擬方法,執行通訊協定調度作業。
- 支援非同步和同步用戶端。不過,非同步用戶端並非安全執行緒。
- 需要 C++14 以上版本。
摘要
類別 | 使用線路類型的新 C++ | 含有自然型別的新 C++ | 高階 C++ |
---|---|---|---|
目標對象 | 驅動程式和效能至關重要的應用程式 | 高階服務 | 高階服務 |
抽象額外負擔 | RAII 關閉句柄 1 | 堆積分配、建構、銷毀 | 堆積分配、建構、銷毀 |
類型安全類型 | 列舉、結構體、聯集、句柄、通訊協定 | 列舉、結構體、聯集、句柄、通訊協定 | 列舉、結構體、聯集、句柄、通訊協定 |
storage | 堆疊、使用者提供的緩衝區或堆積 | 堆積 | 堆積 |
lifecycle | 手動或自動免費 | 自動免費 (RAII) | 自動免費 (RAII) |
接收行為 | 原地解碼 | 將解碼結果解碼至堆積 | 解碼,然後移至堆積 |
傳送行為 | 複製或向量化 | 複製 | 複製 |
呼叫通訊協定方法 | 自由函式或 Proxy | 自由函式或 Proxy | 透過 Proxy 呼叫、註冊回呼 |
實作通訊協定方法 | 手動調度或實作 Stub 介面 | 實作 Stub 介面 | 實作 Stub 物件,叫用回呼 |
非同步用戶端 | 是 | 是 | 是 |
非同步伺服器 | 是 (無上限) 2 | 是 (無上限) [^2] | 是 (無上限) |
平行伺服器調度 | 是 3 | 是 [^3] | no |
產生的程式碼足跡 | large | large | large |
-
產生的類型會擁有內嵌儲存的所有句柄。離線處理常式 (例如指標指向方向後方的常式) 不會在指標的包含物件消失時關閉。在這種情況下,繫結會提供
fidl::DecodedValue
物件,用於管理與呼叫相關聯的所有處理常式。↩ -
在 lib/fidl 中定義的繫結程式庫可透過 lib/fidl/cpp/wire/channel.h 中定義的
fidl::BindServer
,調度無限數量的執行中交易。↩ -
繫結程式庫 lib/fidl 可使用 lib/fidl/cpp/wire/async_transaction.h 中定義的
EnableNextDispatch()
API 啟用並行調度功能。↩