比較新的 C++ 和高階 C++ 語言繫結

快速參考

以下說明如何判斷 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_baselineNew 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
HLCPPstd::string
vector<byte>:64000自然std::vector<uint8_t>
電線fidl::VectorView<uint8_t>
HLCPPstd::vector<uint8_t>
通訊協定儲存庫C++::examples_keyvaluestore_baseline::Store標記類型,可攜帶一些關於通訊協定資訊
HLCPP::examples::keyvaluestore::baseline::Store包含通訊協定中方法的抽象基本類別
client_end:StoreC++fidl::ClientEnd<Store>
HLCPPfidl::InterfaceHandle<Store>
server_end:StoreC++fidl::ServerEnd<Store>
HLCPPfidl::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), diser, &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), diser, &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::vectorstd::optionalstd::string) 表示資料結構。
  • 使用智慧型指標管理堆積分配的物件。
  • 使用 zx::handle 管理句柄擁有權。
  • 可在線路 (例如 fidl::StringView) 和自然類型表示法 (例如 std::string) 之間轉換資料。

線路類型

  • 經過最佳化處理,可滿足低階系統程式設計的需求,同時提供比 C 繫結功能更安全的功能。
  • 代表記憶體配置與線路格式相符的資料結構,也就是符合 C++ 標準配置。這會開啟原地編碼和解碼的門戶。
  • 產生的結構體是底層緩衝區的檢視畫面,不具備記憶體。
  • 支援 FIDL 訊息的當地存取功能。
  • 提供精細的記憶體配置控管機制。
  • 使用自有帳號類型,例如 zx::handle。請注意,由於產生的結構體是底層緩衝區的檢視畫面,因此父項結構體只有在擁有底層緩衝區時,才會擁有子項句柄。舉例來說,FIDL 結構體會擁有內嵌儲存的所有句柄,但包含句柄的結構體 FIDL 向量會以向量檢視畫面表示,不會擁有離線句柄。

用戶端和伺服器 API

  • 與 C 繫結相比,程式碼產生器會產生更多程式碼。這包括建構函式、解構函式、複製/移動函式、網域物件系列之間的轉換、通訊協定用戶端實作項目,以及純虛擬伺服器介面。
  • 使用者可透過子類別化提供的伺服器介面,並覆寫每個作業的純虛擬方法,實作伺服器。
  • 支援同步和非同步呼叫,以及同步和非同步事件處理的用戶端。
  • 需要 C++17 以上版本。

請參閱新版 C++ 教學課程,瞭解如何開始使用。

高階 C++ 繫結

  • 經過最佳化,可滿足高階服務程式設計的需求。
  • 使用慣用 C++ 類型 (例如 std::vectorstd::optionalstd::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
產生的程式碼足跡largelargelarge

  1. 產生的類型會擁有內嵌儲存的所有句柄。離線處理常式 (例如指標指向方向後方的常式) 不會在指標的包含物件消失時關閉。在這種情況下,繫結會提供 fidl::DecodedValue 物件,用於管理與呼叫相關聯的所有處理常式。

  2. lib/fidl 中定義的繫結程式庫可透過 lib/fidl/cpp/wire/channel.h 中定義的 fidl::BindServer,調度無限數量的執行中交易。

  3. 繫結程式庫 lib/fidl 可使用 lib/fidl/cpp/wire/async_transaction.h 中定義的 EnableNextDis() API 啟用並行調度功能。