快速參考指引
以下說明如何識別 C++ 程式碼中的特定類型/函式/ID 是否屬於新的 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++ 繫結中的自然網域物件。「線」是指新 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 | 新的 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 | ||
字串:128 | 自然 | std::string | |
拉線式 | fidl::StringView | ||
HLCPP | std::string | ||
向量<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> | ||
商店通訊協定的 用戶端和伺服器類型 |
自然 | 用戶端: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> 伺服器介面:商店 事件處理常式介面:不適用。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++ (有線)
// 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";
HLCPP
// Connect to the protocol inside the component's namespace, then create an asynchronous client // using the newly-established connection. examples::canvas::baseline::InstancePtr instance_proxy; auto context = sys::ComponentContext::Create(); context->svc()->Connect(instance_proxy.NewRequest(dispatcher)); FX_LOGS(INFO) << "Outgoing connection enabled"; instance_proxy.set_error_handler([&loop](zx_status_t status) { FX_LOGS(ERROR) << "Shutdown unexpectedly"; loop.Quit(); });
如需完整的程式碼清單和說明,請參閱畫布範例。
以下是實作伺服器最常見的方式:
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++ (有線)
// An implementation of the |Instance| protocol. class InstanceImpl final : public fidl::WireServer<examples_canvas_baseline::Instance> { void AddLine(AddLineRequestView request, AddLineCompleter::Sync& completer) override { // ... } };
HLCPP
// An implementation of the |Instance| protocol. class InstanceImpl final : public examples::canvas::baseline::Instance { void AddLine(Line line) 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 和伺服器 API
- 程式碼產生器產生的程式碼比 C 繫結更多。這包括建構函式、解構器、複製/移動函式、網域物件系列之間的轉換、通訊協定用戶端實作,以及純虛擬伺服器介面。
- 使用者可將提供的伺服器介面設為子類別,並覆寫每項作業的純虛擬方法,藉此實作伺服器。
- 支援同步處理和非同步呼叫的用戶端,以及同步和非同步事件處理作業。
- 需要 C++17 以上版本。
如要開始使用,請參閱新 C++ 教學課程。
高階 C++ 繫結
- 經過最佳化處理,符合高階服務程式設計需求。
- 使用慣用的 C++ 類型 (例如
std::vector
、std::optional
和std::string
) 表示資料結構。 - 使用智慧指標管理堆積分配的物件。
- 使用
zx::handle
(libzx) 管理擁有權。 - 能將資料從現有 FIDL 緩衝區轉換為慣用的堆積已配置物件。
- 可將資料從慣用的堆積配置物件 (例如
std::string
) 轉換為就地緩衝區 (例如做為fidl::StringView
)。 - 程式碼產生器產生的程式碼比 C 繫結更多。這包括建構函式、解構器、通訊協定 Proxy、通訊協定虛設常式、複製/移動函式,以及往返就地緩衝區的轉換。
- 用戶端會將提供的虛設常式設為子類別,並為每個作業實作虛擬方法,藉此執行通訊協定分派作業。
- 支援非同步和同步用戶端。然而,非同步用戶端並不安全。
- 需要 C++14 以上版本。
如要開始使用,請參閱 HLCPP 教學課程。
摘要
類別 | 提供傳輸類型的全新 C++ | 具備自然類型的全新 C++ | 高階 C++ |
---|---|---|---|
目標對象 | 驅動程式和著重效能的應用程式 | 高階服務 | 高階服務 |
抽象層 | RAII 關閉帳號代碼1 | 堆積分配、施工、銷毀 | 堆積分配、施工、銷毀 |
類型安全類型 | 列舉, 結構體, 聯集, 控制代碼, 通訊協定 | 列舉, 結構體, 聯集, 控制代碼, 通訊協定 | 列舉, 結構體, 聯集, 控制代碼, 通訊協定 |
儲存空間 | 堆疊、使用者提供的緩衝區或堆積 | 堆積 | 堆積 |
lifecycle | 手動或自動免費 | 自動免費 (RAII) | 自動免費 (RAII) |
接收行為 | 就地解碼 | 解碼為堆積 | 解碼器,然後移至堆積 |
傳送行為 | 複製或向量 | 複製 | 複製 |
呼叫通訊協定方法 | 免費函式或 Proxy | 免費函式或 Proxy | 呼叫、註冊回呼 |
實作通訊協定方法 | 手動調度或實作虛設常式介面 | 實作虛設常式介面 | 實作虛設常式物件、叫用回呼 |
非同步用戶端 | 是 | 是 | 是 |
async server | 是 (無界限) 2 | 是 (無界限) [^2] | 是 (無界限) |
平行伺服器調度 | 是3 | 是 [^3] | 否 |
產生的程式碼足跡 | 大 | 大 | 大 |
-
產生的類型擁有所有內嵌儲存的控制代碼。外線控點 (例如指標包含的物件消失時,位於指標間接後方的控點不會關閉)。在這種情況下,繫結會提供
fidl::DecodedValue
物件,管理與呼叫相關聯的所有控制代碼。↩ -
lib/fidl 中定義的繫結程式庫可透過 lib/fidl/cpp/wire/channel.h 中定義的
fidl::BindServer
,分派無限的執行中交易。↩ -
繫結程式庫 lib/fidl 可使用 lib/fidl/cpp/wire/async_transaction.h 中定義的
EnableNextDispatch()
API 啟用平行調度。↩