Here's how to recognize if a particular type/function/identifier in C++ code is part of the new C++ bindings or high-level C++ bindings.
Taking the examples.keyvaluestore.baseline library as example:
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/new/key_value_store/baseline/fidl/key_value_store.test.fidl" exclude_regexp="^//.*" %}
Here are how the various FIDL elements will map to in the C++ bindings. Note that in the table “C++” refers to the new C++ bindings, and applies equally to both natural domain objects and wire domain objects. “Natural” refers to the natural domain objects in the new C++ bindings. “Wire” refers to the wire domain objects in the new C++ bindings.
Here's the most common way to set up a client:
See the canvas example for the full code listing and explanation.
Here's the most common way to implement a server:
See the canvas example for the full code listing and explanation.
The new C++ bindings supports both low-level and high-level use cases, by offering two families of generated domain objects, and corresponding client and server APIs that speak those types.
Note: prefer natural types unless optimizing for critical performance and memory allocation. Refer to the C++ tutorials.
std::vector, std::optional, and std::string.zx::handle to manage handle ownership.fidl::StringView) and natural type representations (e.g. std::string).zx::handle. Note that since generated structures are views of an underlying buffer, a parent structure will only own child handles if it also owns their underlying buffer. For example, a FIDL struct owns all the handles stored inline, but a FIDL vector of structs containing handles will be represented as a vector view, which will not own the out-of-line handles.Refer to the New C++ tutorial to get started.
<<../../../../_common/_hlcpp_notice.md>>
std::vector, std::optional, and std::string.zx::handle (libzx) to manage handle ownership.std::string) to in-place buffers (e.g. as a fidl::StringView).| Category | New C++ with wire types | New C++ with natural types | High-level C++ |
|---|---|---|---|
| audience | drivers and performance-critical applications | high-level services | high-level services |
| abstraction overhead | RAII closing of handles [^1] | heap allocation, construction, destruction | heap allocation, construction, destruction |
| type safe types | enums, structs, unions, handles, protocols | enums, structs, unions, handles, protocols | enums, structs, unions, handles, protocols |
| storage | stack, user-provided buffer, or heap | heap | heap |
| lifecycle | manual or automatic free | automatic free (RAII) | automatic free (RAII) |
| receive behavior | decode in-place | decode into heap | decode then move to heap |
| send behavior | copy or vectorize | copy | copy |
| calling protocol methods | free functions or proxy | free functions or proxy | call through proxies, register callbacks |
| implementing protocol methods | manual dispatch or implement stub interface | implement stub interface | implement stub object, invoke callbacks |
| async client | yes | yes | yes |
| async server | yes (unbounded) [^2] | yes (unbounded) [^2] | yes (unbounded) |
| parallel server dispatch | yes [^3] | yes [^3] | no |
| generated code footprint | large | large | large |
[^1]: Generated types own all handles stored inline. Out-of-line handles e.g. those behind a pointer indirection are not closed when the containing object of the pointer goes away. In those cases, the bindings provide a fidl::DecodedValue object to manage all handles associated with a call.
[^2]: The bindings library defined in lib/fidl can dispatch an unbounded number of in-flight transactions via fidl::BindServer defined in lib/fidl/cpp/wire/channel.h.
[^3]: The bindings library lib/fidl enables parallel dispatch using the EnableNextDispatch() API defined in lib/fidl/cpp/wire/async_transaction.h.