Fuchsia Interface Definition Language

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 the Echo example, the EchoString() 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, the SendString() 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 the Echo example, the OnString() 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 build system provides the fidl() 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.gn example for the fuchsia.examples library:

# Import the fidl GN template.
import("//build/fidl/fidl.gni")

# Define a FIDL library target.
fidl("fuchsia.examples") {
  # FIDL source files contained in library
  sources = [
    "echo.fidl",
  ]
}

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.

Diagram showing how FIDL bindings provide generated library code to translate
 function calls into FIDL messages for transport across process
  boundaries.

At build time, the fidlgen backend tools generate bindings for supported programming languages from the JSON IR library produced by fidlc. For example, fidlgen_rust generates Rust bindings from the JSON IR.

The fidl() library target creates individual binding targets for each supported language. Due to the nature of GN, these bindings are not generated at build time unless they are included as a dependency.

See the following example BUILD.gn snippet that includes the generated bindings target for the fuchsia.examples library:

Rust

deps = [
  "fidl/fuchsia.examples:fuchsia.examples_rust",
  ...
]

C++

deps = [
  "fidl/fuchsia.examples:fuchsia.examples",
  ...
]

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.

Start by creating a new directory for the FIDL library target:

mkdir -p vendor/fuchsia-codelab/echo-fidl

Create the following file and directory structure in the new project directory:

//vendor/fuchsia-codelab/echo-fidl
                        |- BUILD.gn
                        |- echo.fidl

Add a new FIDL interface file called echo.fidl with the following contents:

library fidl.examples.routing.echo;

const MAX_STRING_LENGTH uint64 = 64;

@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.gn file with the following contents to declare the library target:

import("//build/fidl/fidl.gni")
fidl("echo") {
  name = "fidl.examples.routing.echo"

  sources = [ "echo.fidl" ]

  enable_hlcpp = true
}

Add the library target to the build configuration:

Rust

fx set workstation_eng.x64 --with vendor/fuchsia-codelab/echo-fidl:echo_rust

C++

fx set workstation_eng.x64 --with vendor/fuchsia-codelab/echo-fidl:echo_hlcpp

Examine the FIDL bindings

The fidl() GN target compiles the FIDL interface and generates additional build targets to provide the bindings in various languages. To examine the bindings, you must compile the individual targets.

Compile the fidl.examples.routing.echo bindings:

Rust

fx build vendor/fuchsia-codelab/echo-fidl:echo_rust

C++

fx build vendor/fuchsia-codelab/echo-fidl:echo_hlcpp

Use GN to locate the generated source files for the target and open them in an editor:

Rust

fx gn desc out/default/ vendor/fuchsia-codelab/echo-fidl:echo_rust.actual sources

C++

fx gn desc out/default/ vendor/fuchsia-codelab/echo-fidl:echo_hlcpp sources

Explore the contents of these files. Below is a summary of some of the key generated interfaces:

Rust

Interface Description
EchoMarker Used to open a proxy and request stream for a given protocol.
EchoProxy Asynchronous client that transforms protocol methods into FIDL request messages sent over the IPC channel.
EchoSynchronousProxy Synchronous client that transforms protocol methods into FIDL request messages sent over the IPC channel.
EchoRequest Structured types for handling incoming requests for each protocol method.
EchoRequestStream Stream to handle incoming FIDL request messages over the IPC channel.
EchoEchoStringResponder Callback to send a return value for each proxy request as a FIDL response message.

C++

Interface Description
EchoPtr Asynchronous client that transforms protocol methods into FIDL request messages sent over the IPC channel.
EchoSyncPtr Synchronous client that transforms protocol methods into FIDL request messages sent over the IPC channel.
Echo Abstract class for a server component to override and handle incoming FIDL requests.
EchoStringCallback Callback to send a return value for each request as a FIDL response message.