Use IPC
Lets explore how to use inter-process communication (IPC) between components:
- Define a simple interface protocol that clients can use to ask servers to "Greet".
- Create a server that prints "Hello world" whenever a client asks it to "Greet",
- Create a client that asks the server to "Greet",
Here's what it looks like at runtime:
When we show the static view of components inside executables, it looks like this:
Note that each interface has
- an interface protocol
- a friendly name.
In our example, the client and server both use the same friendly name "hello" for their interfaces, and must use the same protocol (or they wouldn't be able to communicate with each other!).
Define Interface Protocol
First, create a directory for our little project and change directories:
$ mkdir helloIPC $ cd helloIPC
Next, define the interface protocol to use between the client and the server.
To create our greet function-call API, we create a definition file called "greet.api".
$ gedit greet.api
Add this inside greet.api:
FUNCTION Greet ( );
This will declare a function called Greet
that takes no arguments and returns nothing.
Create Server Component
Next, create a server component called greetServer
that offers a greeting service called "hello" to be accessed using our simple "greet" API. Do this by creating a file called "Component.cdef" in a new directory called "greetServer".
$ mkdir greetServer $ gedit greetServer/Component.cdef
- Note
- Keeping components in separate directories from each other is a requirement of the framework.
greetServer/Component.cdef should contain the following:
provides:{api:{hello = greet.api}}sources:{greetServer.c}
This declares that the component named greetServer
(the name of the directory is the name of the component) provides a service called hello
accessed using the API defined in greet.api
where the source code can be found in the file greetServer.c
.
- Note
- The source code file name extension is used to identify the programming language it's written in.
To implement the server (in C), create a file greetServer/greetServer.c
:
$ gedit greetServer/greetServer.c
Make it contain the following:
#include "legato.h"#include "interfaces.h"void hello_Greet(void){LE_INFO("Hello world.");}{}
The file interfaces.h
is auto-generated based on the contents of greet.api
and greetServer's Component.cdef
. It'll contain a prototype of the function hello_Greet()
, which we implemented in greetServer.c
.
The function hello_Greet()
will be called when a client binds to our hello
service and calls the function Greet()
. The name hello_Greet
follows this pattern:
<interface-name> '_' <api-function-name>
The <interface-name> is the name given to the provided interface. In our example, it's the name hello
before the =
in the line hello
=
greet.api
.
- Note
- If you forget to implement a service function on the server or if you give it the wrong name, the link stage will fail and complain that the symbol is unresolved. You'll know you missed a function, and you'll be able to see what the correct name of the function should be.
Create Client Component
Now that we have a server, let's create a client to use its service.
First, create a directory for the greetClient
component and a file in it called Component.cdef:
$ mkdir greetClient $ gedit greetClient/Component.cdef
greetClient/Component.cdef should contain:
requires:{api:{hello = greet.api}}sources:{greetClient.c}
To implement the client using C, create a file called greetClient/greetClient.c
:
$ gedit greetClient/greetClient.c
Make it contain the following:
#include "legato.h"#include "interfaces.h"{hello_Greet();}
The interfaces.h
file the client includes is different than the one the server uses. This client one is specially generated based on the contents of greetClient/Component.cdef
and greet.api
.
In the client, we use the component initializer to call hello_Greet()
at start-up.
You can add a message to the COMPONENT_INIT so the logs will show the client calling the server:
{LE_INFO("greetClient is calling hello_Greet \n");hello_Greet();}
Declare IPC Availability
You can create an Application Definition .adef file with an extern section to declare the app is available for binding:
extern:{helloWorld.greetServer.greet.api}
You only need to do this if you want to leave your interface unbound, and bind it later in the .sdef file bindings section.
Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.