For the C language, five files are generated from the component interface file:
The ifgen
usage details are generated by the -h
or –help
options:
usage: ifgen [-h] [--gen-all] [--gen-interface] [--gen-local] [--gen-client] [--gen-server-interface] [--gen-server] [--async-server] [--name-prefix NAMEPREFIX] [--file-prefix FILEPREFIX] [--output-dir OUTPUTDIR] [--import-dir IMPORTDIRS] [--no-default-prefix] [--hash] [--dump] FILE Interface Code Generator positional arguments: FILE name of interface file optional arguments: -h, --help show this help message and exit --gen-all generate all files; overrides individual file options --gen-interface generate interface header file --gen-local generate local header file --gen-client generate client IPC implementation file --gen-server-interface generate server interface header file --gen-server generate server IPC implementation file --async-server generate asynchronous-style server functions --name-prefix NAMEPREFIX optional prefix for generated functions/types; defaults to input filename --file-prefix FILEPREFIX optional prefix for generated files; defaults to input file name --output-dir OUTPUTDIR optional output directory for generated files --import-dir IMPORTDIRS optional directory for imported files; may be given multiple times --no-default-prefix do not use default file or name prefix if none is specified --hash print SHA256 hash for interface; NO files are generated --dump print info on parsed functions; NO files are generated
–async-server option
There are two alternatives to implement the server-side functionality.
The default case is where each server-side function has the same interface as the client-side function. The server-side function takes the IN parameters, and returns the OUT parameters when the function exits.
In the async-server case, the server-side function doesn't necessarily return the OUT parameters when it exits. Instead, there's a separate Respond
function for each server-side function. The OUT parameters are returned by passing these OUT parameters to the Respond
function. The Respond
function can be called at any time, normally after the server-side function has exited.
Regardless of how the server-side functions are implemented, the client-side function waits until the OUT parameters are returned.
This is how a handler in an interface file is mapped to actual C definitions (based on the API File Sample).
HANDLER TestA { HANDLER_PARAMS ( int32 x ); ADD_HANDLER_PARAMS (); };
This results in two type definitions and two function definitions:
typedef void (*TestAFunc_t) ( int32_t x, void* contextPtr ); typedef struct TestA* TestARef_t; TestARef_t AddTestA ( TestAFunc_t handlerPtr, void* contextPtr ); void RemoveTestA ( TestARef_t addHandlerRef );
Required parameters for the two functions are added automatically. Since ADD_HANDLER_PARAMS
parameterList
wasn't given, additional parameters weren't added to the ADD_HANDLER function.
A contextPtr
parameter has been automatically added to both the definition of the function pointer, and the definition of the ADD_HANDLER function. The contextPtr
passed to the ADD_HANDLER function, will be passed back to the HANDLER
function. If the contextPtr
is not needed, then NULL can be used.
These are client-specific functions:
void StartClient ( const char* serviceInstanceName ); void StopClient ( void );
To use a service, an initial connection to the server must be created using StartClient()
. Only needs to be called once per process; normally done in the COMPONENT_INIT function of the client application. This creates the connection for the main thread. Connections used by other threads are created automatically if other threads use a function provided by a service.
If a client application uses multiple services, multiple StartClient()
functions need to be called; each function will have an appropriate prefix to distinguish these clients. If multiple client applications are used, each application must be initialized separately, using the appropriate StartClient() function.
The StopClient() function is used to close a connection to the server. It only closes the connection for the current thread, so must be called separately for each thread that uses a service. At some point later, if a thread starts to use a service, then the connection will be automatically re-created for that thread.
These are server-specific functions:
le_msg_ServiceRef_t GetServiceRef ( void ); le_msg_SessionRef_t GetClientSessionRef ( void ); void StartServer ( const char* serviceInstanceName );
To provide a service, the server must advertise the service to any interested clients using StartServer()
. Should be called in the COMPONENT_INIT function of the server daemon implementation.
If a server provides multiple services, multiple StartServer()
functions need to be called; each function will have an appropriate prefix to distinguish each service.
The GetServiceRef()
function is used to get the server session reference for the current service. Required if the server uses any of the server-specfic Low-Level Messaging API functions for this service.
For example, le_msg_SetServiceCloseHandler can be used by the server to register a close handler whenever a client closes its connection. This may be needed to cleanup client specific data maintained by the server.
GetClientSessionRef()
function is used to get the client session reference for the current service. This client session is only valid while executing the server-side function that implements an interface function. Once this server-side function returns, the client session can no longer be retrieved. GetClientSessionRef()
is needed if the server wants to call any of the client specific Low-Level Messaging API functions for this service.
For example, le_msg_GetClientUserId() can be used by the server to determine the UserId of the client using the service, which allows the server to perform any necessary UserId based authentication.
Here's the generated client interface header file for the common.api file from API File Sample
/* * ====================== WARNING ====================== * * THE CONTENTS OF THIS FILE HAVE BEEN AUTO-GENERATED. * DO NOT MODIFY IN ANY WAY. * * ====================== WARNING ====================== */ /** * Common definitions potentially used across multiple .api files */ #ifndef COMMON_H_INCLUDE_GUARD #define COMMON_H_INCLUDE_GUARD #include "legato.h" //-------------------------------------------------------------------------------------------------- /** * Definition example */ //-------------------------------------------------------------------------------------------------- #define COMMON_SOME_VALUE 5 //-------------------------------------------------------------------------------------------------- /** * Example of using previously DEFINEd symbol within an imported file. */ //-------------------------------------------------------------------------------------------------- #define COMMON_TEN 10 //-------------------------------------------------------------------------------------------------- /** * Reference example */ //-------------------------------------------------------------------------------------------------- typedef struct common_OpaqueReference* common_OpaqueReferenceRef_t; //-------------------------------------------------------------------------------------------------- /** * ENUM example */ //-------------------------------------------------------------------------------------------------- typedef enum { COMMON_ZERO, ///< first enum COMMON_ONE, ///< second enum COMMON_TWO, ///< third enum COMMON_THREE ///< fourth enum } common_EnumExample_t; #endif // COMMON_H_INCLUDE_GUARD
Here's the generated client interface header file for the example.api file from API File Sample
/* * ====================== WARNING ====================== * * THE CONTENTS OF THIS FILE HAVE BEEN AUTO-GENERATED. * DO NOT MODIFY IN ANY WAY. * * ====================== WARNING ====================== */ /** * Example API file */ #ifndef EXAMPLE_H_INCLUDE_GUARD #define EXAMPLE_H_INCLUDE_GUARD #include "legato.h" // Interface specific includes #include "common_interface.h" //-------------------------------------------------------------------------------------------------- /** * Start the service for the client main thread */ //-------------------------------------------------------------------------------------------------- void example_StartClient ( const char* serviceInstanceName ///< [IN] ); //-------------------------------------------------------------------------------------------------- /** * Stop the service for the current client thread */ //-------------------------------------------------------------------------------------------------- void example_StopClient ( void ); //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- #define EXAMPLE_TEN 10 //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- #define EXAMPLE_TWENTY 20 //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- #define EXAMPLE_SOME_STRING "some string" //-------------------------------------------------------------------------------------------------- /** * Reference type for example_TestA handler ADD/REMOVE functions */ //-------------------------------------------------------------------------------------------------- typedef struct example_TestA* example_TestARef_t; //-------------------------------------------------------------------------------------------------- /** * Handler definition * * @param x * First parameter for the handler * Second comment line * @param contextPtr */ //-------------------------------------------------------------------------------------------------- typedef void (*example_TestAFunc_t) ( int32_t x, void* contextPtr ); //-------------------------------------------------------------------------------------------------- /** * example_TestA handler ADD function */ //-------------------------------------------------------------------------------------------------- example_TestARef_t example_AddTestA ( example_TestAFunc_t handlerPtr, ///< [IN] void* contextPtr ///< [IN] ); //-------------------------------------------------------------------------------------------------- /** * example_TestA handler REMOVE function */ //-------------------------------------------------------------------------------------------------- void example_RemoveTestA ( example_TestARef_t addHandlerRef ///< [IN] ); //-------------------------------------------------------------------------------------------------- /** * Function takes all the possible kinds of parameters, but returns nothing */ //-------------------------------------------------------------------------------------------------- void example_allParameters ( common_EnumExample_t a, ///< [IN] ///< first one-line comment ///< second one-line comment uint32_t* bPtr, ///< [OUT] const uint32_t* dataPtr, ///< [IN] size_t dataNumElements, ///< [IN] uint32_t* outputPtr, ///< [OUT] ///< some more comments here ///< and some comments here as well size_t* outputNumElementsPtr, ///< [INOUT] const char* label, ///< [IN] char* response, ///< [OUT] ///< comments on final parameter, first line ///< and more comments size_t responseNumElements ///< [IN] ); //-------------------------------------------------------------------------------------------------- /** * Test file descriptors as IN and OUT parameters */ //-------------------------------------------------------------------------------------------------- void example_FileTest ( int dataFile, ///< [IN] ///< file descriptor as IN parameter int* dataOutPtr ///< [OUT] ///< file descriptor as OUT parameter ); #endif // EXAMPLE_H_INCLUDE_GUARD
Copyright (C) Sierra Wireless, Inc. 2014. All rights reserved. Use of this work is subject to license.