Fuchsia Interface Definition Language (FIDL) is the language used to describe interprocess communication (IPC) protocols used by Fuchsia programs. FIDL provides a simplified declaration syntax for providers to define interfaces as a protocol. Supported data types include integers, floats, booleans, strings, and handles . These can be organized into more complex arrays, vectors, structs, tables, and unions.
Consider the following example FIDL protocol for an Echo
interface:
library fuchsia.examples;
const MAX_STRING_LENGTH uint64 = 32;
@discoverable
closed protocol Echo {
strict EchoString(struct {
value string:MAX_STRING_LENGTH;
}) -> (struct {
response string:MAX_STRING_LENGTH;
});
strict SendString(struct {
value string:MAX_STRING_LENGTH;
});
strict -> OnString(struct {
response string:MAX_STRING_LENGTH;
});
};
FIDL protocols describe a set of methods invoked by sending messages over a channel. Channel messages are inherently asynchronous, with the sender and receiver operating independently of each other. FIDL methods introduce higher-level semantics that enable more idiomatic programming on the client and server side of a FIDL transaction.
FIDL supports the following method types:
- Two-way methods: A typical method call that accepts optional parameters
with a return type defined after the
->
operator. Two-way methods block until a response is received. In theEcho
example, theEchoString()
method is a two-way method. - One-way methods: Asynchronous method calls that return immediately
without waiting for a response. Methods without a declared return type are
considered one-way from the client. In the
Echo
example, theSendString()
method is a one-way method. - Events: When necessary, a server may send unsolicited messages to the
client, called events. Events declare their method name on the return side of
the
->
operator. In theEcho
example, theOnString()
method is an event.
Creating a FIDL library
FIDL libraries group FIDL source files together. A library acts as a namespace for the protocols it contains, and FIDL source files can implicitly access all other declarations within the same library. FIDL source files must import any declarations from another library.
The Fuchsia SDK provides the fuchsia_fidl_library()
build target to compile
FIDL source files into a library. The name of the library target must match the
library
declarations in each source file. See the following BUILD.bazel
example for the fuchsia.examples
library:
# Import the fidl template.
load("fuchsia_fidl_library")
# Define a FIDL library target.
fuchsia_fidl_library(
name = "fuchsia.examples",
srcs = [
"echo.fidl",
],
library = ""fuchsia.examples"",
visibility = ["//visibility:public"],
)
At build time, the FIDL Compiler (fidlc
) frontend tool validates and compiles
the library source files into a JSON Intermediate Representation (IR). This JSON
IR format is the basis for the FIDL bindings.
Generating FIDL bindings
Components consume FIDL protocols through generated code called FIDL bindings. Bindings encode and decode requests and responses as FIDL messages and transfer them over the underlying IPC channel. The language-specific binding libraries provide wrappers around these structures to align interactions with familiar programming idioms.
The client interface (sometimes referred to as a proxy) performs translation between higher-level function calls and FIDL messages. On the server side, bindings process incoming request messages and deliver them through an abstract interface for components to implement.
At build time, the fidlgen
backend tools generate bindings for supported
programming languages from the JSON IR library produced by fidlc
.
The Fuchsia SDK provides build templates to generate bindings for each supported
language. See the following BUILD.bazel
example to generate HLCPP bindings for
the fuchsia.examples
library:
fuchsia_fidl_hlcpp_library(
name = "fuchsia.examples.fidl_cc",
library = ":fuchsia.examples",
visibility = ["//visibility:public"],
deps = [
"@fuchsia_sdk//pkg/fidl_cpp",
],
)
Components that consume this library can use the bindings target as a dependency.
Exercise: Echo FIDL Library
In this section, you'll define a new FIDL library with a protocol called
Echo
containing a single method that returns string values back to the
caller.
Create the FIDL library
Start by creating a new directory for the FIDL library target:
mkdir -p fuchsia-codelab/echo-fidl
After you complete this section, the project should have the following directory structure:
//fuchsia-codelab/echo-fidl
|- BUILD.bazel
|- echo.fidl
Add a new FIDL interface file called echo.fidl
with the following contents:
echo-fidl/echo.fidl
:
library examples.routing.echo;
const MAX_STRING_LENGTH uint64 = 32;
@discoverable
closed protocol Echo {
/// Returns the input.
strict EchoString(struct {
value string:<MAX_STRING_LENGTH, optional>;
}) -> (struct {
response string:<MAX_STRING_LENGTH, optional>;
});
};
EchoString
is a two-way method that accepts an optional (nullable) string
value and returns the same value.
Add a BUILD.bazel
file with the following contents to declare the library
target:
echo-fidl/BUILD.bazel
:
load(
"@fuchsia_sdk//fuchsia:defs.bzl",
"fuchsia_fidl_library",
"fuchsia_fidl_llcpp_library",
)
package(default_visibility = ["//visibility:public"])
fuchsia_fidl_library(
name = "examples.routing.echo",
srcs = [
"echo.fidl",
],
library = "examples.routing.echo",
)
fuchsia_fidl_llcpp_library(
name = "examples.routing.echo.fidl_cc",
library = ":examples.routing.echo",
deps = [
"@fuchsia_sdk//pkg/fidl_cpp_v2",
],
)
Run bazel build
and verify that the build completes successfully:
bazel build --config=fuchsia_x64 //fuchsia-codelab/echo-fidl:examples.routing.echo.fidl_cc
Examine the FIDL bindings
The FIDL bindings target compiles the FIDL interface and generates
language-specific bindings in the bazel-bin/
directory:
bazel-bin/fuchsia-codelab/echo-fidl/_virtual_includes/
Locate and open the generated headers found in the above directory:
find bazel-bin/fuchsia-codelab/echo-fidl/_virtual_includes -name *.h
Explore the contents of these files. Below is a summary of some of the key generated interfaces:
Interface | Description |
---|---|
Echo
|
Represents the FIDL protocol and acts as the main entry point for types and classes that both clients and servers use to interact with that protocol. |
EchoString
|
Representation of the FIDL protocol method, used by clients and servers to provide typed requests and responses. |
fidl::Server<Echo>
|
Abstract class for a server component to override and handle incoming FIDL requests. |
fidl::internal::NaturalClientImpl<Echo>
|
Asynchronous client that transforms protocol methods into FIDL request
messages sent over the IPC channel. Provided when a fidl::Client
is created for this protocol.
|
fidl::internal::NaturalSyncClientImpl<Echo>
|
Synchronous client that transforms protocol methods into FIDL request
messages sent over the IPC channel. Provided when a fidl::SyncClient
is created for this protocol.
|