| # HLCPP bindings | |
| ## Libraries {#libraries} | |
| Given the library declaration: | |
| ```fidl | |
| library fuchsia.examples; | |
| ``` | |
| All code for this library is generated in the `fuchsia::examples` namespace, and | |
| [test scaffolding](#test-scaffolding) is generated in | |
| `fuchsia::examples::testing`. | |
| ## Constants {#constants} | |
| All [constants][lang-constants] are generated as a `constexpr`. For example, the | |
| following constants: | |
| ```fidl | |
| {%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="consts" %} | |
| ``` | |
| Are generated in the header file as: | |
| ```c++ | |
| constexpr uint8_t BOARD_SIZE = 9u; | |
| extern const char[] NAME; | |
| ``` | |
| The correspondence between FIDL primitive types and C++ types is outlined in | |
| [built-in types](#builtins). Instead of `constexpr`, strings are declared as an | |
| `extern const char[]` in the header file, and defined in a `.cc` file. | |
| ## Fields {#fields} | |
| This section describes how the FIDL toolchain converts FIDL types to native | |
| types in HLCPP. These types can appear as members in an aggregate type or as | |
| parameters to a protocol method. | |
| ### Built-in types {#builtins} | |
| The FIDL types are converted to C++ types based on the following table: | |
| |FIDL Type|HLCPP Type| | |
| |--- |--- | | |
| |`bool`|`bool`| | |
| |`int8`|`int8_t`| | |
| |`int16`|`int16_t`| | |
| |`int32`|`int32_t`| | |
| |`int64`|`int64_t`| | |
| |`uint8`|`uint8_t`| | |
| |`uint16`|`uint16_t`| | |
| |`uint32`|`uint32_t`| | |
| |`uint64`|`uint64_t`| | |
| |`float32`|`float`| | |
| |`float64`|`double`| | |
| |`array:N`|`std::array`| | |
| |`vector:N`|`std::vector`| | |
| |`vector:N?`|`fidl::VectorPtr`| | |
| |`string`|`std::string`| | |
| |`string?`|`fidl::StringPtr`| | |
| |`request<P>`, `request<P>?`|`fidl::InterfaceRequest`| | |
| |`P`,`P?`|`fidl::InterfaceHandle`| | |
| |`handle`, `handle?`|`zx::handle`| | |
| |`handle:S`, `handle:S?`|The corresponding zx type is used. For example, `zx::vmo` or `zx::channel`.| | |
| ### User defined types {#user-defined-types} | |
| In HLCPP, a user defined type (bits, enum, constant, struct, union, or table) is | |
| referred to in the bindings using the generated class or variable (see [Type | |
| Definitions](#type-definitions)). For a nullable user-defined type `T`, | |
| `unique_ptr` of the equivalent generated type is used. | |
| ### Request, response, and event parameters {#request-response-event-parameters} | |
| Whenever FIDL needs to generate a single type representing parameters for a | |
| request, response, or event (e.g. when generating [`fit::result` compatible result types](#protocols-results)), | |
| it uses the following rules: | |
| * Multiple arguments are generated as an `std::tuple` of the parameter types. | |
| * A single parameter is just referred to using the parameter type itself. | |
| * An empty set of parameters is represented using `void`. | |
| ## Type definitions {#type-definitions} | |
| ### Bits {#bits} | |
| Given the [bits][lang-bits] definition: | |
| ```fidl | |
| {%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="bits" %} | |
| ``` | |
| The FIDL toolchain generates a C++ `enum class` using the specified underlying | |
| type, or `uint32_t` if none is specified: | |
| ```c++ | |
| enum class FileMode : uint16_t { | |
| READ = 1u; | |
| WRITE = 2u; | |
| EXECUTE = 4u; | |
| }; | |
| ``` | |
| In addition, FIDL generates the following methods for `FileMode`: | |
| * Bitwise operators: implementations for the `|`, `|=`, `&`, `&=`, `^`, `^=`, | |
| and `~` operators are generated, allowing bitwise operations on the bits like | |
| `mode |= FileMode::EXECUTE`. | |
| FIDL also generates a `const static FileMode FileModeMask` variable. This is a | |
| bitmask containing all of the bits in the enum class, which can be used to get | |
| rid of any unused bit values from a raw underlying `uint16_t` (or whichever type | |
| the `bits` are based on). In the above example, `FileModeMask` has a value of | |
| `0b111`. | |
| Example usage: | |
| ```c++ | |
| {%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/hlcpp/unittests/main.cc" region_tag="bits" adjust_indentation="auto" exclude_regexp="^TEST|^}" %} | |
| ``` | |
| ### Enums {#enums} | |
| Given the [enum][lang-enums] definition: | |
| ```fidl | |
| {%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="enums" %} | |
| ``` | |
| The FIDL toolchain generates an equivalent C++ `enum class` using the specified | |
| underlying type, or `uint32_t` if none is specified: | |
| ```c++ | |
| enum class LocationType : uint32_t { | |
| MUSEUM = 1u; | |
| AIRPORT = 2u; | |
| RESTAURANT = 3u; | |
| }; | |
| ``` | |
| Example usage: | |
| ```c++ | |
| {%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/hlcpp/unittests/main.cc" region_tag="enums" adjust_indentation="auto" exclude_regexp="^TEST|^}" %} | |
| ``` | |
| ### Structs {#structs} | |
| Given a [struct][lang-structs] declaration: | |
| ```fidl | |
| {%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="structs" %} | |
| ``` | |
| The FIDL toolchain generates a `Color` type with public members and methods. | |
| * `public` members: | |
| * `uint32_t id{}`: This field is zero-initialized since no default value is | |
| provided. | |
| * `std::string name = "red"`: The corresponding field for `name`. | |
| * Methods: | |
| * `static inline std::unique_ptr<Color> New()`: returns a `unique_ptr` to a | |
| new `Color`. | |
| The 6 special members of `Color` (default, copy and move constructor, | |
| destructor, copy and move assignment) are implicitly defined. | |
| `Color` also has the following associated generated values: | |
| * `ColorPtr`: an alias to `unique_ptr<Color>`. | |
| Structs may have additional members if they represent the response variant of a | |
| [result](#protocols-results). | |
| Example usage: | |
| ```c++ | |
| {%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/hlcpp/unittests/main.cc" region_tag="structs" adjust_indentation="auto" exclude_regexp="^TEST|^}" %} | |
| ``` | |
| ### Unions {#unions} | |
| Given the union definition: | |
| ```fidl | |
| {%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="unions" %} | |
| ``` | |
| FIDL generates a `JsonValue` class. `JsonValue` contains a public tag enum | |
| representing the possible [variants][union-lexicon]: | |
| ```c++ | |
| enum Tag : fidl_xunion_tag_t { | |
| kIntValue = 2, | |
| kStringValue = 3, | |
| Invalid = std::numeric_limits<fidl_xunion_tag_t>::max(), | |
| }; | |
| ``` | |
| Each member of `Tag` has a value matching its [ordinal][union-lexicon] specified | |
| in the `union` definition. Reserved fields do not have any generated code. In | |
| addition, there is an `Invalid` field which is the initial value used for a | |
| `JsonValue` that has no variant set yet. | |
| `JsonValue` provides the following methods: | |
| * `JsonValue()`: Default constructor. The tag is initially `Tag::Invalid` until | |
| the `JsonValue` is set to a specific variant. Using the `WithFoo` constructors | |
| should be preferred whenever possible. | |
| * `~JsonValue()`: Default destructor | |
| * `static JsonValue WithIntValue(int32&&)` and `static JsonValue | |
| WithStringValue(std::string&&)`: Static constructors that directly construct a | |
| specific variant of the union. | |
| * `static inline std::unique_ptr<JsonValue> New()`: Returns a `unique_ptr` to a | |
| new `JsonValue` | |
| * `bool has_invalid_tag()`: Returns `true` if the instance of `JsonValue` does | |
| not yet have a variant set. Users should not access a union until a variant | |
| is set - doing so should be considered undefined behavior. | |
| * `bool is_int_value() const` and `bool is_string_value() const`: Each variant | |
| has an associated method to check whether an instance of `JsonValue` is of | |
| that variant | |
| * `const int32_t& int_value() const` and `const std::string& string_value() | |
| const`: Read-only accessor methods for each variant. These methods fail if | |
| `JsonValue` does not have the specified variant set | |
| * `int32_t& int_value()` and `std::string& string_value()`: Mutable accessor | |
| methods for each variant. If the `JsonValue` has a different variant than the | |
| called accessor method, it will destroy its current data and re-initialize it | |
| as the specified variant. | |
| * `JsonValue& set_int_value(int32_t)` and `JsonValue& | |
| set_string_value(std::string)`: Setter methods for each variant. | |
| * `Tag Which() const`: returns the current [tag][union-lexicon] of the | |
| `JsonValue`. | |
| * `fidl_xunion_tag_t Ordinal() const`: returns the raw `fidl_xunion_tag_t` tag. | |
| Prefer to use `Which()` unless the raw ordinal is required | |
| `JsonValue` also has the following associated generated values: | |
| * `JsonValuePtr`: an alias to `unique_ptr<Foo>`. | |
| Unions may have additional methods if they represent the response variant of a | |
| [result](#protocols-results). | |
| Example usage: | |
| ```c++ | |
| {%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/hlcpp/unittests/main.cc" region_tag="unions" adjust_indentation="auto" exclude_regexp="^TEST|^}" %} | |
| ``` | |
| #### Flexible unions and unknown variants | |
| This section describes differences in generated code if `JsonValue` were marked | |
| as [`flexible`][lang-unions]. Flexible unions have an extra variant in the | |
| generated `Tag`: | |
| ```c++ | |
| enum Tag : fidl_xunion_tag_t { | |
| kUnknown = 0, | |
| ... // other fields omitted | |
| }; | |
| ``` | |
| When a FIDL message containing a union with an unknown variant is decoded into | |
| `JsonValue`, `JsonValue::Which()` returns `JsonValue::Tag::kUnknown`, and | |
| `JsonValue::Ordinal()` returns the unknown ordinal. | |
| A flexible `JsonValue` also has the following extra methods: | |
| * `const vector<uint8_t>* UnknownData() const`: Returns the raw bytes of the | |
| union variant if it is unknown, or `nullptr` otherwise. | |
| HLCPP does not support encoding a `JsonValue` if it has an unknown ordinal. | |
| Re-encoding a union with an unknown variant does not write the unknown bytes | |
| back onto the wire, instead encoding an absent union. Therefore, encoding a | |
| message with an uninitialized union only succeeds if this union is allowed to be | |
| absent (i.e. if it is specified as `JsonValue?` instead of `JsonValue`). | |
| Non-flexible (i.e. `strict`) unions fail when decoding a data containing an | |
| unknown variant. | |
| ### Tables {#tables} | |
| Given the [table][lang-tables] definition: | |
| ```table | |
| {%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="tables" %} | |
| ``` | |
| The FIDL toolchain generates a `User` class with the following methods: | |
| * `User()`: Default constructor, initializes with all fields unset. | |
| * `User(User&&)`: Move constructor. | |
| * `~User()`: Destructor. | |
| * `User& User::operator=(User&&)`: Move assignment. | |
| * `bool IsEmpty() const`: Returns true if no fields are set. | |
| * `bool has_age() const` and `bool has_name() const`: Returns whether a field is | |
| set. | |
| * `const uint8_t& age() const` and `const std::string& name() const`: Read-only | |
| field accessor methods. These fail if the field is not set. | |
| * `uint8_t* mutable_age()` and `std::string* mutable_name()`: Mutable field | |
| accessor methods. If the field is not set, a default one will be constructed, | |
| set, and returned. | |
| * `User& set_age(uint8_t)` and `User& set_name(std::string)`: Field setters. | |
| * `void clear_age()` and `void clear_name()`: Clear the value of a field by | |
| calling its destructor | |
| `User` also has the following associated generated values: | |
| * `UserPtr`: an alias to `unique_ptr<User>`. | |
| Example usage: | |
| ```c++ | |
| {%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/hlcpp/unittests/main.cc" region_tag="tables" adjust_indentation="auto" exclude_regexp="^TEST|^}" %} | |
| ``` | |
| ## Protocols {#protocols} | |
| Given the [protocol][lang-protocols]: | |
| ```fidl | |
| {%includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples/types.test.fidl" region_tag="protocols" %} | |
| ``` | |
| Note: The `MakeMove` method above returns a bool representing success, and a | |
| nullable response value. This is considered un-idiomatic, you should use an [error type](#protocols-results) | |
| instead. | |
| FIDL generates a `TicTacToe` class, which acts as an entry point for interacting | |
| with the protocol and defines the interface of the service which is used by | |
| clients to proxy calls to the server, and for the server for implementing the | |
| protocol. Synchronous clients use a different virtual interface, `TicTacToe_Sync`. | |
| `TicTacToe` contains the following member types: | |
| * `MakeMoveCallback` and `OnOpponentMoveCallback`: Each response and event has a | |
| member type generated that represents the type of the callback for handling | |
| that response or event. In the above example, `MakeMoveCallback` aliases | |
| `fit::function<void(bool, std::unique_ptr<GameState>)>` and | |
| `OnOpponentMoveCallback` aliases `fit::function<void(GameState)>`. | |
| `TicTacToe` additionally has the following pure virtual methods, corresponding | |
| to the methods in the protocol definition: | |
| * `virtual void StartGame(bool start_first)`: Pure virtual method for a fire and | |
| forget protocol method. It takes as arguments the request parameters. | |
| * `virtual void MakeMove(uint8_t row, uint8_t col, MakeMoveCallback callback)`: | |
| Pure virtual method for a two way protocol method. It takes as arguments the | |
| request parameters followed by the response handler callback. | |
| `TicTacToe_Sync` has the following pure virtual methods, corresponding to the | |
| methods in the protocol definition: | |
| * `virtual zx_status_t StartGame(bool start_first)`: Pure virtual method for a | |
| fire and forget protocol method. It takes as arguments the request parameters, | |
| and returns a `zx_status_t` representing whether the request was sent | |
| successfully. | |
| * `virtual zx_status_t MakeMove(uint8_t row, uint8_t col, bool* out_success, std::unique_ptr<GameState>* out_new_state)`: Pure virtual method for a two way | |
| method protocol. It takes as arguments the request parameters, followed by | |
| output pointers for each of the response parameters. It returns a `zx_status_t` | |
| representing whether the method call was made successfully. | |
| Other code may be generated depending on the | |
| [attributes](#protocol-and-method-attributes) applied to the protocol or its | |
| methods. | |
| ### Client {#protocols-client} | |
| The FIDL toolchain generates two aliases for the classes used to make calls to a | |
| `TicTacToe` server : `TicTacToePtr`, which aliases | |
| `fidl::InterfacePtr<TicTacToe>` representing an async client, and | |
| `TicTacToeSyncPtr`, which aliases `fidl::SynchronousInterfacePtr<TicTacToe>` | |
| representing a synchronous client. | |
| When dereferenced, `TicTacToePtr` and `TicTacToeSyncPtr` return a proxy class | |
| that implements `TicTacToe` and `TicTacToe_Sync`, respectively, which proxies | |
| requests to the server. In this example, given a `TicTacToePtr` called | |
| `async_tictactoe`, requests could be made by calling | |
| `async_tictactoe->StartGame(start_first)` or `async_tictactoe->MakeMove(row, | |
| col, callback)`. | |
| Examples on how to set up and bind an `InterfacePtr` or a | |
| `SynchronousInterfacePtr` to a channel are covered in the | |
| [HLCPP tutorial][client-tut]. | |
| ### Server | |
| Implementing a server for a FIDL protocol involves providing a concrete | |
| implementation of `TicTacToe`. | |
| Examples on how to set up and bind a server implementation are covered in the | |
| HLCPP tutorial. | |
| ### Events {#events} | |
| #### Client | |
| For a `TicTacToePtr` `tictactoe`, `tictactoe.events()` returns a proxy class | |
| that contains the following public members: | |
| * `OnOpponentMoveCallback OnOpponentMove`: The callback handler for the | |
| `OnOpponentMove` event. | |
| Clients can handle events by setting the members of this class to the desired | |
| event handlers. | |
| Refer to the [top-level generated protocol code](#protocols) for details on the | |
| callback types. | |
| #### Server | |
| For a `Binding<TicTacToe>` `tictactoe`, `tictactoe.events()` returns a stub | |
| class that contains the following public members: | |
| * `void OnOpponentMove(GameState new_state)`: Send an `OnOpponentMove`. | |
| The [tutorial][server-tut] has an example for obtaining a `Binding`. | |
| ### Results {#protocols-results} | |
| Given the method with an error type: | |
| ```fidl | |
| protocol TicTacToe { | |
| MakeMove(uint8 row, uint8 col) -> (GameState new_state) error MoveError; | |
| }; | |
| ``` | |
| FIDL generates code so that clients and servers can use `fit::result` in place | |
| of the generated `MakeMove` response type. This is done by generating a | |
| `TicTacToe_MakeMove_Result` class to represent the response that is | |
| interchangeable with `fit::result<GameState, MoveError>`. Using this feature, an | |
| example implementation of `MakeMove` on the server side could look like: | |
| ```c++ | |
| void MakeMove(MakeMoveCallback callback) override { | |
| callback(fit::ok(game_state_.state())); | |
| // or, in the error case: callback(fit::error(Error::kInvalid); | |
| } | |
| ``` | |
| An example of using this on the client side, in the async case would be: | |
| ```c++ | |
| async_game->MakeMove([&](fit::result<GameState, MoveError>> response) { ... }); | |
| ``` | |
| When generating code, the FIDL toolchain treats `TicTacToe_MakeMove_Result` as a | |
| `union` with two variants: `response`, which is a generated type described | |
| below, and `err`, which is the error type (in this case `uint32`), which means | |
| that it provides all the methods available to a [regular union](#unions). In | |
| addition, `TicTacToe_MakeMove_Result` provides methods that allow interop with | |
| `fit::result`: | |
| * `TicTacToe_MakeMove_Result(fit::result<GameState, MoveError>&& result)`: Move | |
| constructor from a `fit::result`. | |
| * `TicTacToe_MakeMove_Result(fit::ok_result<GameState>&& result)`: Move | |
| constructor from a `fit::ok_result`. | |
| * `TicTacToe_MakeMove_Result(fit::error_result<MoveError>&& result)`: Move | |
| constructor from a `fit::error_result`. | |
| * `operator fit::result<GameState, MoveError>() &&`: Conversion to a | |
| `fit::result`. | |
| Note that the successful result type parameter of the `fit::result` follows the | |
| [parameter type conversion rules](#protocol-and-method-attributes): if | |
| `MakeMove` returned multiple values on success, the result type would be a tuple | |
| of the response parameters `fit::result<std::tuple<...>, ...>`, and if | |
| `MakeMove` returned an empty response, the result type would be | |
| `fit::result<void, ...>`. | |
| The FIDL toolchain also generates a `TicTacToe_MakeMove_Response` class, which | |
| is the type of the `response` variant of `TicTacToe_MakeMove_Result`. This class | |
| is treated as a FIDL struct with fields corresponding to each parameter of the | |
| successful response. In addition to the methods and members available to a | |
| [regular struct](#structs), `TicTacToe_MakeMove_Response` provides additional | |
| methods that allow interop with `std::tuple`: | |
| * `explicit TicTacToe_MakeMove_Response(std::tuple<GameState> _value_tuple)`: | |
| Constructor from a tuple. | |
| * `operator std::tuple<GameState>() &&`: Conversion operator for a tuple. | |
| ### Protocol composition {#protocol-composition} | |
| FIDL does not have a concept of inheritance, and generates full code as | |
| described above for all [composed protocols][lang-protocol-composition]. In | |
| other words, the code generated for | |
| ```fidl | |
| protocol A { | |
| Foo(); | |
| }; | |
| protocol B { | |
| compose A; | |
| Bar(); | |
| }; | |
| ``` | |
| Provides the same API as the code generated for: | |
| ```fidl | |
| protocol A { | |
| Foo(); | |
| }; | |
| protocol B { | |
| Foo(); | |
| Bar(); | |
| }; | |
| ``` | |
| The generated code is identical except for the method ordinals. | |
| ### Protocol and method attributes {#protocol-and-method-attributes} | |
| #### Transitional | |
| For protocol methods annotated with the | |
| [`[Transitional]`](/docs/reference/fidl/language/attributes.md#transitional) | |
| attribute, the `virtual` methods on the protocol class are not pure. This allows | |
| implementations of the protocol class with missing method overrides to compile | |
| successfully. | |
| #### Discoverable {#discoverable} | |
| A protocol annotated with the | |
| [`[Discoverable]`](/docs/reference/fidl/language/attributes.md#discoverable) | |
| attribute causes the FIDL toolchain to generate an additional `static const char | |
| Name_[]` field on the protocol class, containing the full protocol name. For a | |
| protocol `Baz` in the library `foo.bar`, the generated name is `"foo.bar.Baz"`. | |
| ### Test scaffolding {#test-scaffolding} | |
| The FIDL toolchain also generates a file suffixed with `_test_base.h` that | |
| contains convenience code for testing FIDL server implementations. This file | |
| contains a class for each protocol that provides stub implementations for each | |
| of the class’s methods, making it possible to implement only the methods that | |
| are used during testing. These classes are generated into a `testing` namespace | |
| that is inside of the generated library’s namespace (e.g. for library | |
| `games.tictactoe`, these classes are generated into | |
| `games::tictactoe::testing`). | |
| For the same `TicTacToe` protocol listed above, the FIDL toolchain generates a | |
| `TicTacToe_TestBase` class that subclasses `TicTacToe` (see | |
| [Protocols](#protocols)), offering the following methods: | |
| * `virtual ~TicTacToe_TestBase() {}`: Destructor. | |
| * `virtual void NotImplemented_(const std::string& name) = 0`: Pure virtual | |
| method that is overridden to define behavior for unimplemented methods. | |
| `TicTacToe_TestBase` provides an implementation for the virtual protocol methods | |
| `StartGame` and `MakeMove`, which are implemented to just call | |
| `NotImplemented_("StartGame")` and `NotImplemented_("MakeMove")`, respectively. | |
| <!-- xrefs --> | |
| [client-tut]: /docs/development/languages/fidl/tutorials/hlcpp/basics/client.md | |
| [server-tut]: /docs/development/languages/fidl/tutorials/hlcpp/basics/server.md | |
| [lang-constants]: /docs/reference/fidl/language/language.md#constants | |
| [lang-bits]: /docs/reference/fidl/language/language.md#bits | |
| [lang-enums]: /docs/reference/fidl/language/language.md#enums | |
| [lang-structs]: /docs/reference/fidl/language/language.md#structs | |
| [lang-tables]: /docs/reference/fidl/language/language.md#tables | |
| [lang-unions]: /docs/reference/fidl/language/language.md#unions | |
| [lang-protocols]: /docs/reference/fidl/language/language.md#protocols | |
| [lang-protocol-composition]: /docs/reference/fidl/language/language.md#protocol-composition | |
| [union-lexicon]: /docs/reference/fidl/language/lexicon.md#union-terms |