All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
C Language Support

For the C language, five files are generated from the component interface file:

  • client interface header file (interface.h) - C definitions for the interface. This file should be included by any C source files that want to use the interface.
  • server header file (server.h) - C definitions for the server interface. There is some duplication between this file and the interface file, but it also contains definitions that are not part of the public client interface. This file should be included by any C source files that want to implement the interface.
  • local header file (local.h) - local header file provides common definitions for the client and server implementations. This file should only be included by the client and server implementation files.
  • client implementation file (client.c) - implements all of the interface functions. These functions handle the details of sending messages to the server, and processing the responses.
  • server implementation file (server.c) - implements handlers for all the interface functions. These handlers receive the message from the client side, call the corresponding real implementation of the function, and generate any responses back to the client side.
Note
Client and server implementation files are provided to support client/server IPC implementations.

Interface Generation Tool

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.

Note
In the async-server option only, OUT parameters are both the function return value and any explicit OUT parameters defined for the function.

Handlers in C

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.

Client Specific Functions

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.

Server Specific Functions

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.

API File Sample Output

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.