新的 C++ 繫結教學課程

本節將協助您瞭解如何使用新的 C++ FIDL 繫結。詳情請見 開始使用 從頭開始建構及編寫簡單的用戶端或伺服器查看主題 ,提供相關指南和建議,協助您瞭解如何有效使用繫結。 請參閱術語,瞭解所發名稱和概念 並快速說明如何做出正確選擇。

大致上,C++ 繫結由以下元素組成:

  • 資料網域物件 ( 產生的 FIDL 結構,例如結構體、資料表、...)
  • 行為:供用戶端/伺服器 API 透過 通訊協定、接收事件...

自然和電線域的物體

這些繫結支援兩種網域物件:natural 類型和 類型:

  • 自然類型是針對人體工學最佳化的高層級網域物件。
    • 這些型別會使用智慧指標負責子項。
    • 這類函式會使用慣用的 C++ 類型,例如 std::vectorstd::optionalstd::string
    • 如果有名為 fuchsia.my.lib 的 FIDL 程式庫,系統就會產生類型 在 fuchsia_my_lib 命名空間中。
  • 類型已針對效能最佳化,並就地解碼。
    • 這些是特殊的 C++ 標準版面配置類型,其記憶體佈局 符合 FIDL 線格式。
    • 行外子項是進入獨立緩衝區的無從指標。 請參閱接線網域物件的記憶體擁有權
    • 如果有名為 fuchsia.my.lib 的 FIDL 程式庫,系統就會產生類型 在 fuchsia_my_lib::wire 命名空間中。

啟動專案時,預設選擇自然類型,因為比較容易使用 而且效能合理最佳化時只轉做電線類型 或需要精確控制記憶體時 分配速度。由於線路類型包含不安全的檢視畫面,不當使用 以免使用釋放後記憶體 以及其他記憶體安全錯誤

開始使用

  1. 使用自然來源和線路域物體
  2. 寫入伺服器
  3. 寫入用戶端 (非同步同步)

主題

術語

用戶端和伺服器的WireWire相比

如果用戶端/伺服器 API 名稱中出現 Wire 前置字串,代表 API 已啟用 只接受電線類型。否則,API 通常可以接受 或預設為自然型別例如:fidl::Client 支援透過自然或有線方式撥打電話, fidl::WireClient 提供限制更嚴格的介面,只接受有線 。

fidl::Server」會接收自然類型的要求,但可能會傳送以下回覆: 自然或線路類型另一方面,fidl::WireServer獲得 轉交連線類型,並專門傳送電線類型回覆。

為了在不使用功能的情況下同時支援傳訊端的線路和自然類型 過載不明確的問題,電線介面是放在 .wire() 存取子底下。 以 fidl::Client<MyProtocol> client; 為例 client->SomeMethod(natural_type); 會透過自然類型提出要求 client.wire()->SomeMethod(wire_type); 以使用線路類型提出要求。

建議

使用不含 Wire 前置字串的用戶端/伺服器 API。只有在必要時 確保在編譯期間只使用線型,其中一種可能定義了函式 使用 Wire 對應工具的簽章,例如:fidl::WireClient。其中之一 這也取決於繫結的電線部分,具體方式取決於 fuchsia.my.lib_cpp_wire目標而非 fuchsia.my.lib_cpp GN 目標。

客戶的Sync對比 sync

同步或「同步」適用於包含回應的 FIDL 呼叫 表示通話處於封鎖狀態:發出這類呼叫的執行緒不會 ,直到回應傳回為止。例如: fidl::WireSyncClient 是所有雙向呼叫都同步的用戶端。 同樣地,fidl::WireClient.sync() 存取子會傳回 發出同步呼叫的介面。

單向呼叫沒有回應,因此同步性的概念 不適用於它們

建議

如果程式碼是獨立程式,只會取用來自其他 Google 服務的能力 元件,決定其業務需求所需的並行程度:

  • 如果沒有管理大量並行作業,您可以使用 方便閱讀直行邏輯。舉例來說 短執行的指令列工具可能會使用 fidl::SyncClient

  • 如果您的程式碼管理大量並行作業,通常就能存取 非同步調度工具 (async_dispatcher_t*)。選擇合適的解決方案時 在這種情況下,最好使用 非同步版本例如,使用 fidl::WireClient 但不參加 透過 .sync() 透過 fidl::WireSyncClient.sync() 送達。尤其是 如果調度工具為單個,則不要在調度器執行緒上同步呼叫 執行緒,以避免死結

如果您的程式碼是服務,也就是提供 應使用非同步調度器和非同步用戶端 可支援多位消費者所需的並行

如果您的程式碼是其他應用程式使用的程式庫, 再三考慮是否應該公開同步或 配合使用者需求調整非同步介面舉例來說 以及提供同步介面和 更加難以使用 實作非同步調度工具

以上是一般建議,不同非同步執行階段 提供更具體的建議

客戶的Shared對比 shared

當用戶端類型為「共用」時物件可能會在容器上繫結至 任意執行緒查看執行緒中的 SharedClient 指南。有一個不含「分享」的對應項目,例如 Client。 必須在調度工具執行緒上繫結和刪除。類似關係 介於 WireClientWireSharedClient 之間。

建議

選擇 ClientSharedClient 時,請改選 Client,除非應用程式的執行緒或效能需求 應用程式需要透過多執行緒使用用戶端。詳情請參閱 執行緒指南,瞭解使用 SharedClientClient 的額外限制旨在 可以降低記憶體競爭,以及使用釋放後使用的記憶體。例如,您可以使用 Client 物件也會出現在相同的單一執行緒非同步調度工具上。

雙向通話的ThenThenExactlyOnce

當非同步呼叫具有回應時,有兩種方法可以指定 回呼以接收該呼叫的結果:

  • 使用 .ThenExactlyOnce(...) 時,系統一律會明確呼叫回呼 然後傳送結果
  • 使用 .Then(...) 時,系統會在用戶端時自動捨棄回呼,而且不會顯示通知 物件已被刪除,因此適用於物件導向程式碼。

Then」的動機

進行非同步雙向呼叫時,系統會傳送這次呼叫的結果 執行已經離開應用程式,讓您可以之後再返回應用程式 發出呼叫的原始範圍非同步調度器之後 叫用您在進行呼叫時指定的後續追蹤邏輯 (稱為 。物件一經刪除後就要容易使用 導致記憶體損毀:

// The following snippet shows an example of use-after-free
// occurring in asynchronous two-way calls.
void Foo(fidl::WireClient<MyProtocol>& client) {
  bool call_ok;
  client->SomeMethod().Then(
      // The following lambda function represents the continuation.
      [&call_ok] (fidl::WireUnownedResult<SomeMethod>& result) {
        // `call_ok` has already gone out of scope.
        // This would lead to memory corruption.
        call_ok = result.ok();
      });
}

當接續擷取時 this 指標,而說的參照物件也擁有用戶端。刪除 外部物件 (進而刪除用戶端) 會導致所有待處理物件 呼叫失敗。接續執行時,它擷取的 this 指標不會 的時間。

ThenThenExactlyOnce 都會登錄雙向呼叫的接續作業。 不過,Then 的設計宗旨是減輕上述的損毀情況。 具體違規事項如下:

  • Then 會確保最多只會呼叫一次提供的接續作業,直到 用戶端就會遭到刪除。如果只有接續程序,應選擇 Then 擷取生命週期與用戶端相同的物件 (例如:使用者物件) 客戶擁有)。刪除使用者物件會導致 回呼函式。使用釋放後不會有使用上的疑慮。

  • 另一方面,ThenExactlyOnce 可保證呼叫接續 (僅執行一次)。如果用戶端物件遭到刪除,接續就會收到 取消錯誤。請務必確認所有參照的物件仍使用中 也就是持續執行時,可能是在 用戶端物件也會遭到刪除。請選用 ThenExactlyOnce, 連續呼叫只能呼叫一次,例如與 fpromise 個完成者或 FIDL 伺服器完成程式,或在單元測試期間。

建議

原則上:

  • 如果您的回呼類似 client_->Foo([this],請使用 Then (請注意, client_ 是成員變數)。
  • 如果你的回呼看起來像
    • client->Foo([completer],或
    • client->Foo([],或
    • client->Foo([&] (常見於單元測試),
    • 回呼會擷取弱指標或強弱指標
    • 使用 ThenExactlyOnce

請勿擷取不同生命週期的物件,只讓 物件會在接續執行時運作。

Zircon 管道運輸與驅動程式庫運送

FIDL 通訊協定與在 FIDL 定義,用來判斷可能經歷的資源種類 通訊協定,也可能影響系統為傳送和接收作業產生的 API 訊息。C++ 繫結支援兩種傳輸方式:

Zircon 管道傳輸是以端點類型表示 《fidl::ClientEnd<SomeProtocol>》和《fidl::ServerEnd<SomeProtocol>》。

驅動程式傳輸使用端點類型 fdf::ClientEnd<SomeProtocol>fdf::ServerEnd<SomeProtocol>

競技場

Arenas 物件會管理記憶體緩衝區集區,並提供有效的分配作業。 這些都普遍用於傳輸領域物件,並連接電線用戶端和伺服器, 避免使用昂貴的複本

競技場不會用於自然領域物件和相關用戶端, 封裝了記憶體配置的詳細資料。

您可以使用 fidl::Arena 建立存線網域物件 體育場館請參閱「記憶體管理」。

透過驅動程式傳輸使用通訊協定時 網域物件,應使用 fdf::Arena 物件來分配緩衝區 需要將訊息編碼