blob: 04c92990b31e5f34a24e900f62ba162c92896312 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// ============================================================================
// This is an accompanying example code for the C++ client tutorial. Head over
// there for the full walk-through:
// https://fuchsia.dev/fuchsia-src/development/languages/fidl/tutorials/cpp/basics/client
// ============================================================================
// [START includes]
#include <fidl/fuchsia.examples/cpp/wire.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/syslog/cpp/macros.h>
// [END includes]
// [START main]
int main(int argc, const char** argv) {
// Connect to the |fuchsia.examples/Echo| 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<fuchsia_examples::Echo>();
if (!client_end.is_ok()) {
FX_LOGS(ERROR) << "Synchronous error when connecting to the |Echo| protocol: "
<< client_end.status_string();
return -1;
}
async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);
async_dispatcher_t* dispatcher = loop.dispatcher();
// Define the event handler implementation for the client.
//
// The event handler delegate should be an object that implements the
// |fidl::WireAsyncEventHandler<Echo>| virtual class, which has methods
// corresponding to the events offered by the protocol. By default those
// methods are no-ops.
// [START event-handler-short]
class EventHandler : public fidl::WireAsyncEventHandler<fuchsia_examples::Echo> {
public:
void OnString(fidl::WireEvent<fuchsia_examples::Echo::OnString>* event) override {
FX_LOGS(INFO) << "(Natural types) got event: " << event->response.get();
loop_.Quit();
}
// [END event-handler-short]
// One may also override the |on_fidl_error| method, which is called
// when the client encounters an error and is going to teardown.
void on_fidl_error(fidl::UnbindInfo error) override { FX_LOGS(ERROR) << error; }
explicit EventHandler(async::Loop& loop) : loop_(loop) {}
private:
async::Loop& loop_;
};
// Create an instance of the event handler.
EventHandler event_handler(loop);
// Create a client to the Echo protocol, passing our |event_handler| created
// earlier. The |event_handler| must live for at least as long as the
// |client|. The |client| holds a reference to the |event_handler| so it is a
// bug for the |event_handler| to be destroyed before the |client|.
// [START init-client-short]
fidl::WireClient client(std::move(*client_end), dispatcher, &event_handler);
// [END init-client-short]
// Make an EchoString call, passing it a lambda to handle the result asynchronously.
// |result| contains the method response or a transport error if applicable.
client->EchoString("hello").ThenExactlyOnce(
[&](fidl::WireUnownedResult<fuchsia_examples::Echo::EchoString>& result) {
// Check if the FIDL call succeeded or not.
if (!result.ok()) {
// If the call failed, log the error, and crash the program.
// Production code should do more graceful error handling depending
// on the situation.
FX_LOGS(ERROR) << "EchoString failed: " << result.error();
ZX_PANIC("%s", result.error().FormatDescription().c_str());
}
// Dereference (->) the result object to access the response payload.
std::string_view response = result->response.get();
FX_LOGS(INFO) << "Got response: " << response;
loop.Quit();
});
// Run the dispatch loop, until we receive a reply, in which case the callback
// above will quit the loop, breaking us out of the |Run| function.
loop.Run();
loop.ResetQuit();
// [START sync-call]
// Make a synchronous EchoString call, which blocks until it receives the response,
// then returns a WireResult object for the response.
fidl::WireResult result_sync = client.sync()->EchoString("hello");
ZX_ASSERT(result_sync.ok());
std::string_view response = result_sync->response.get();
FX_LOGS(INFO) << "Got synchronous response: " << response;
// [END sync-call]
// Make a SendString request. The resulting OnString event will be handled by
// the event handler defined above.
fidl::Status status_oneway = client->SendString("hi");
// Check for any synchronous errors.
ZX_ASSERT(status_oneway.ok());
loop.Run();
return 0;
}
// [END main]