Clients

Client code is code that accesses the facilities of components as described by those components' interfaces, potentially via interprocess communications mechanisms. Given an interface description featuring component operations, code may be written to invoke these operations and to treat the component as if it resides in the same program, even if it actually resides in another program operating as a server.

  1. Introduction
  2. Client Header Files
  3. C Language Clients
  4. C++ Language Clients
  5. Accessing Component Servers
  6. Example Code

Introduction

The following example interface, resident in a file called calc.idl, will be used to illustrate the mechanisms described in this document:

interface Calc
{
  void add(in int left, in int right, out int result);
  void subtract(in int left, in int right, out int result);
  void multiply(in int left, in int right, out int result);
  void divide(in int numerator, in int denominator, out int result);
};

To use this interface, a client program would do the following:

The sections below describe how this is done in the different supported programming languages.

Note that the mechanism by which interface descriptions are processed for use in programs is described in the L4Re Support document. The idl manual page provides details for developers wishing to use the tool directly.

Client Header Files

Given the existence of generated files for the interface, a program would include the client header file:

#include "calc_client.h"

To obtain references to components via the L4Re environment, the following include statement is required:

#include <l4/re/env.h>

C Language Clients

An object representing the component will have the Calc type. This encapsulates a reference to the object state and a reference to the interface details.

The object state can be populated using a capability in L4Re:

ref_Calc ref = {.cap=server};

However, the state of a local object would be populated using a pointer:

ref_Calc ref = {.ptr=local_state};

The Calc object is initialised using the chosen reference value and a predefined interface reference:

Calc obj = {.ref=ref, .iface=&client_iface_Calc};

This predefined interface reference is obtained via the header file.

To call interface operations, the functions providing access to them can be called directly:

Calc_add(ref, 123, 456, &result);

However, this ignores the object type and just employs the reference to the object state. A more object-oriented approach involves using the interface:

obj.iface->add(obj.ref, 123, 456, &result);

By employing object type values (instances), it becomes possible to treat local and remote components interchangeably.

C++ Language Clients

An object representing the component will have the Calc type. A client object employing a capability in L4Re is a subtype of Calc called client_Calc and would be initialised as follows:

client_Calc obj(server);

Meanwhile, an object implemented locally might have a type called local_Calc and be initialised as follows:

local_Calc obj;

Such a local object would also need to be defined as a subtype of Calc.

These objects can then be used to call interface operations:

obj.add(123, 456, &result);

Since a common base class is used to declare the interface, local and remote components are interchangeable.

Accessing Component Servers

In L4Re, components can be made available to programs via capabilities provided in the program environment. Given the presence of such a capability, registered with the name of server and associated with a component server, access to the remote component can be obtained as follows:

l4_cap_idx_t server = l4re_env_get_cap("server");

Thereafter, the techniques described above should be sufficient to communicate with and invoke the operations of the component.

Example Code

The pkg/idl4re-examples directory contains some example packages for L4Re that feature some of the above code and demonstrate the techniques involved. The idl4re-examples directory can be copied into the L4Re distribution's pkg directory and built as follows:

make O=mybuild S=pkg/idl4re-examples

The mybuild directory name should be adjusted to match your own choice of build output directory.