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

快速參考指引

以下說明如何在 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++ 繫結,並同樣適用於 使用自然領域物件和通訊網域物件「自然」是指 自然領域物件「電匯」是指電線網域 新 C++ 繫結中的物件。

FIDL 元素 C++ 自然型別 留言
標頭包括 C++ #包含 <fidl/examples.keyvaluestore.baseline/cpp/fidl.h> 格式為「fidl/library name/cpp/fidl.h」
HLCPP #包含 <範例>/keyvaluestore/baseline/cpp/fidl.h> 格式為「斜線分隔程式庫 name/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
string:128 自然 std::字串
拉線式 fidl::StringView
HLCPP std::字串
向量<byte>:64000 自然 std::向量<uint8_t>
拉線式 fidl::VectorView&lt;uint8_t&gt;
HLCPP std::向量<uint8_t>
通訊協定存放區 C++ ::examples_keyvaluestore_baseline::Store 包含通訊協定相關資訊的標記類型
HLCPP ::examples::keyvaluestore::baseline::Store 包含通訊協定中方法的抽象基本類別
client_end:Store C++ fidl::ClientEnd&lt;Store&gt;
HLCPP fidl::InterfaceHandle&lt;Store&gt;
server_end:Store C++ fidl::ServerEnd&lt;Store&gt;
HLCPP fidl::InterfaceRequest&lt;Store&gt;
商店通訊協定
的用戶端和伺服器類型
自然 用戶端: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::vectorstd::optionalstd::string
  • 使用智慧指標管理堆積分配的物件。
  • 請使用 zx::handle 管理擁有權。
  • 可在接線 (例如 fidl::StringView) 和自然線之間轉換資料 型別表示法 (例如 std::string)。

電匯類型

  • 可滿足低階系統程式設計需求,同時提供 安全性與功能略高
  • 代表資料結構,其記憶體配置與電線一致 也就是滿足 C++ 標準版面配置的需求這樣就能開啟 直接編碼和解碼
  • 產生的結構是基礎緩衝區的檢視區塊;非他們所有 記憶體用量
  • 支援就地存取 FIDL 訊息。
  • 精細控管記憶體配置。
  • 使用自有帳號代碼類型,例如 zx::handle。請注意 結構是基礎緩衝區的檢視畫面,父項結構只會 自己的子項會處理。舉例來說 FIDL 結構體擁有所有內嵌於內嵌的控制代碼,但結構體的 FIDL 向量 內含控點將以向量檢視畫面表示,但不具擁有權 運用脫字線控點

用戶端和伺服器 API

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

如要開始使用,請參閱新的 C++ 教學課程

高階 C++ 繫結

  • 可滿足高階服務程式設計需求。
  • 使用慣用的 C++ 類型表示資料結構,例如 std::vectorstd::optionalstd::string
  • 使用智慧指標管理堆積分配的物件。
  • 請使用 zx::handle (libzx) 管理帳號代碼擁有權。
  • 可以將就地的 FIDL 緩衝區資料轉換為分配的慣用堆積 如需儲存大量結構化物件 建議使用 Cloud Bigtable
  • 可以從慣用的堆積分配物件中轉換資料 (例如 std::string) 到就地緩衝區 (例如 fidl::StringView)。
  • 與 C 繫結相比,程式碼產生器產生的程式碼會更多。這包括 建構函式、解構函式、通訊協定 Proxy、通訊協定虛設常式、複製/移動 函式,以及往返就地緩衝區的轉換。
  • 用戶端會把提供的虛設常式分化,以執行通訊協定分派作業,並 為每個作業實作虛擬方法
  • 系統支援非同步和同步用戶端。不過,非同步用戶端 不符合執行緒安全要求
  • 需要 C++14 以上版本。

如要開始使用,請參閱 HLCPP 教學課程

摘要

類別 支援線路類型的新 C++ 含有自然型別的新 C++ 高階 C++
目標對象 能夠和著重效能的應用程式 高階服務 高階服務
抽象化負荷 RAII 帳號代碼關閉1 堆積分配、建構、刪除 堆積分配、建構、刪除
類型安全類型 列舉、結構體、聯集、控點、通訊協定 列舉、結構體、聯集、控點、通訊協定 列舉、結構體、聯集、控點、通訊協定
儲存空間 堆疊、使用者提供的緩衝區或堆積 堆積 堆積
生命週期 手動或自動免費 自動免費 (RAII) 自動免費 (RAII)
接收行為 就地解碼 解碼成堆積 並移至堆積
傳送行為 複製或向量化 複製 複製
呼叫通訊協定方法 免費函式或 Proxy 免費函式或 Proxy 透過 Proxy 呼叫、註冊回呼
實作通訊協定方法 手動分派或實作虛設常式介面 實作虛設常式介面 實作虛設常式物件、叫用回呼
非同步用戶端
非同步伺服器 是 (無限制) 2 是 (不設限) [^2] 是 (無限制)
平行伺服器調度 3 是 [^3]
產生的程式碼足跡

  1. 產生的類型擁有內嵌儲存的所有控制代碼。虛線控點 例如:當包含容器時 指標的 物件會消失在這些情況下,繫結會提供 fidl::DecodedValue 物件,用於管理與呼叫相關的所有帳號代碼。

  2. lib/fidl 中定義的繫結程式庫可以 透過 fidl::BindServer 分派不受限的傳輸中交易數量 lib/fidl/cpp/wire/channel.h.

  3. 繫結程式庫 lib/fidl 可啟用平行處理功能 傳送 EnableNextDispatch()API lib/fidl/cpp/wire/async_transaction.h.