C Runtime Library

This section contains detailed info about Legato's C Language library used for low-level routines like commonly used data structures and OS services APIs.


The C APIs' Overview has high-level info.


Legato Build Configuration
Basic Type and Constant Definitions
Command Line Arguments API
Directory API
Doubly Linked List API
Dynamic Memory Allocation API
Event Loop API
File Descriptor Monitor API
File Locking API
HashMap API
Hex string API
Logging API
Low-Level Messaging API
Mutex API
Path API
Path Iterator API
Print APIs
System Clock API
Safe References API
Semaphore API
Signals API
Singly Linked List API
Thread Control API
Timer API
Unit Testing API
UTF-8 String Handling API

Overview

Here is some background info on Legato's C Language APIs.

Design

The Legato framework is constructed in an object-oriented manner.

The C programming language was created before object-oriented programming was popular so it doesn't have native support for OOP features like inheritance, private object members, member functions, and overloading. But object-oriented designs can still be implemented in C.

In the Legato C APIs, classes are hidden behind opaque "reference" data types. You can get references to objects created behind the scenes in Legato, but you can never see the structure of those objects. The implementation is hidden from view. Access to object properties is made available through accessor functions.

Types

The basic "opaque data type" offered by the C programming language is the "void pointer" (void *). The idea is that a pointer to an object of type T can be cast to point to a void type before being passed outside of the module that implements T.

This makes it impossible for anyone outside of the module that implements T to dereference the pointer or access anything about the implementation of T. This way, the module that implements T is free to change the implementation of T in any way needed without worrying about breaking code outside of that module.

The problem with the void pointer type is that it throws away type information. At compile time, this makes it impossible to detect that a variable with opaque type T has been passed into a function with some other pointer type P.

To overcome this, Legato uses incomplete types to implement its opaque types. For example, there are declarations similar to the following in Legato C API header files:

// Declare a reference type for referring to Foo objects.
typedef struct le_foo* le_foo_Ref_t;

But "struct le_foo" would not be defined in the API header or anywhere outside of the hypothetical Foo API's implementation files. This makes "struct le_foo" an "incomplete type" for all code outside of the Foo API implementation files. Incomplete types can't be used because the compiler doesn't have enough information about them to generate any code that uses them. But pointers to incomplete types can be passed around because the compiler always knows the pointer size. The compiler knows that one incomplete type is not necessarily interchangeable with another. It won't allow a pointer to an incomplete type to be used where a pointer to another type is expected.


Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.