實作 FIDL 用戶端

必要條件

本教學課程是以 FIDL 伺服器教學課程為基礎。如需完整的 FIDL 教學課程,請參閱總覽

總覽

本教學課程會實作 FIDL 通訊協定的用戶端,並針對先前教學課程中建立的伺服器執行用戶端。本教學課程中的用戶端為同步作業。我們也提供其他教學課程,可用於非同步用戶端。

如果您想自行編寫程式碼,請刪除下列目錄:

rm -r examples/fidl/hlcpp/client_sync/*

建立元件

examples/fidl/hlcpp/client_sync 中建立新的元件專案:

  1. main() 函式新增至 examples/fidl/hlcpp/client_sync/main.cc

    int main(int argc, const char** argv) {
      printf("Hello, world!\n");
      return 0;
    }
    
  2. examples/fidl/hlcpp/client_sync/BUILD.gn 中為用戶端宣告目標:

    import("//build/components.gni")
    
    
    # Declare an executable for the client.
    executable("bin") {
      output_name = "fidl_echo_hlcpp_client_sync"
      sources = [ "main.cc" ]
    }
    
    fuchsia_component("echo-client") {
      component_name = "echo_client"
      manifest = "meta/client.cml"
      deps = [ ":bin" ]
    }
    
  3. examples/fidl/hlcpp/client_sync/meta/client.cml 中新增元件資訊清單:

    {
        include: [ "syslog/client.shard.cml" ],
    
        // Information about the program to run.
        program: {
            // Use the built-in ELF runner.
            runner: "elf",
    
            // The binary to run for this component.
            binary: "bin/fidl_echo_hlcpp_client_sync",
        },
    
        // Capabilities used by this component.
        use: [
            { protocol: "fuchsia.examples.Echo" },
        ],
    }
    
    
  4. 建立元件後,請確認您可以將其新增至建構設定:

    fx set core.x64 --with //examples/fidl/hlcpp/client_sync:echo-client
    
  5. 建構 Fuchsia 映像檔:

    fx build
    

編輯 GN 依附元件

  1. 新增下列依附元件:

      deps = [
        "//examples/fidl/fuchsia.examples:fuchsia.examples_hlcpp",
        "//sdk/lib/sys/cpp",
      ]
    
    
  2. 然後將這些值加入 main.cc

    #include <fuchsia/examples/cpp/fidl.h>
    #include <lib/sys/cpp/component_context.h>
    

    伺服器教學課程說明瞭為何要加入這些依附元件。

連線至伺服器

本節新增 main() 函式的程式碼,用於連線至伺服器並對伺服器提出要求。

初始化 Proxy 類別

接著,程式碼會為 Echo 通訊協定建立 Proxy 類別,並將其連結至伺服器。在 FIDL 的上下文中,proxy 是指由 FIDL 繫結產生的程式碼,可讓使用者向伺服器發出遠端程序呼叫。在 HLCPP 中,Proxy 會採用類別的形式,其中的方法會對應至每個 FIDL 通訊協定方法。

int main(int argc, const char** argv) {
  fuchsia::examples::EchoSyncPtr echo_proxy;
  auto context = sys::ComponentContext::Create();
  context->svc()->Connect(echo_proxy.NewRequest());

  ZX_ASSERT(echo_proxy->SendString("hi") == ZX_OK);
  std::string response;
  ZX_ASSERT(echo_proxy->EchoString("hello", &response) == ZX_OK);
  printf("Got response: %s\n", response.c_str());

  // TODO(fcz): this currently does not pass on CQ
  // return response == "hello" ? 0 : 1;
  return 0;
}
  • fuchsia::examples::EchoSyncPtr 是繫結產生的 fidl::SynchronousInterfaceRequest<fuchsia::examples::Echo> 別名。這個類別會透過繫結的管道,為 Echo 通訊協定要求建立 Proxy。
  • 程式碼會呼叫 EchoSyncPtr::NewRequest(),這會建立管道、將類別繫結至某端,然後傳回另一端
  • 回傳的結束時間會傳遞至 sys::ServiceDirectory::Connect()
    • 與伺服器端對 context->out()->AddPublicService() 的呼叫相似,Connect 在此處有隱含的第二個參數,即通訊協定名稱 ("fuchsia.examples.Echo")。這就是前一個教學課程中定義的處理常式輸入來源:用戶端將其傳遞至 Connect,再由 Connect 傳遞至處理常式。

請注意,這段程式碼假設 /svc 已包含 Echo 通訊協定的例項。根據預設,由於元件架構提供的沙箱,因此並非如此。

將要求傳送至伺服器

程式碼會向伺服器提出兩項要求:

  • EchoString 要求
  • SendString 要求
int main(int argc, const char** argv) {
  fuchsia::examples::EchoSyncPtr echo_proxy;
  auto context = sys::ComponentContext::Create();
  context->svc()->Connect(echo_proxy.NewRequest());

  ZX_ASSERT(echo_proxy->SendString("hi") == ZX_OK);
  std::string response;
  ZX_ASSERT(echo_proxy->EchoString("hello", &response) == ZX_OK);
  printf("Got response: %s\n", response.c_str());

  // TODO(fcz): this currently does not pass on CQ
  // return response == "hello" ? 0 : 1;
  return 0;
}

如果是 EchoString,程式碼會針對每個回應參數傳遞指標 (在本例中,EchoString 方法只有一個回應參數),這是由伺服器的回應所寫入,但這不適用於 SendString,因為這是啟動和忘記方法。系統會封鎖對 EchoString 的呼叫,直到收到伺服器的訊息為止。這兩種方法都會傳回 zx_status_t,指出方法呼叫的結果。

雖然伺服器實作會回應 SendString 要求來傳送 OnString 事件,但同步處理繫結並不會提供處理這個事件的方法。

執行用戶端

為了讓用戶端和伺服器使用 Echo 通訊協定進行通訊,元件架構必須將 fuchsia.examples.Echo 能力從伺服器路由至用戶端。在本教學課程中,我們會使用

  1. 設定建構作業,加入提供的套件,其中包含回音領域、伺服器和用戶端:

    fx set core.x64 --with //examples/fidl/hlcpp:echo-hlcpp-client-sync
    
  2. 建構 Fuchsia 映像檔:

    fx build
    
  3. 執行 echo_realm 元件。這會建立用戶端和伺服器元件執行個體,並將功能導向:

    ffx component run /core/ffx-laboratory:echo_realm fuchsia-pkg://fuchsia.com/echo-hlcpp-client-sync#meta/echo_realm.cm
    
  4. 啟動 echo_client 執行個體:

    ffx component start /core/ffx-laboratory:echo_realm/echo_client
    

當用戶端嘗試連線至 Echo 通訊協定時,伺服器元件就會啟動。您應該會在裝置記錄 (ffx log) 中看到類似以下的輸出內容:

[echo_server][][I] Running echo server
[echo_client][][I] Got response: hello

終止領域元件,停止執行並清理元件例項:

ffx component destroy /core/ffx-laboratory:echo_realm