Generating Server Bindings for C in libadr

This section provides examples for generating server bindings for C.

Example 3-6 Generating Server Bindings for C

$ radadrgen -l c -s server -d output_dir example.adr

The C library argument to radadrgen produces two files, api_APINAME.h and api_APINAME_impl.c in the output_dir, where APINAME is derived from the name attribute of the API document's api element. api_APINAME_impl.c contains the implementation of the interfaces and data types defined by the API. It should be compiled and linked with the software needing those definitions.

api_APINAME.h externs the specific symbols defined by api_APINAME_impl.c that consumers will need to reference, and should be included by those consumers. api_APINAME.h contains no data definitions itself and may be included in as many places as necessary. Neither file should be modified.

For each derived type TYPE, whether enumeration or structure, defined in the API, an adr_type_t named t__TYPE (two underscores) representing that type is generated and externed by the header file. If an array of that type is used anywhere in the API, an adr_type_t named t_array__TYPE (one underscore, two underscores) representing that array type is generated and externed. For each interface INTERFACE defined in the file, an adr_object_t named interface_INTERFACE is defined and externed.

For each value VALUE of an enumeration named TYPE, an adr_data_t named e__TYPE_VALUE is defined and externed. These adr_data_t values are marked as constants and are not affected by adr_data_ref or adr_data_free.

When radadrgen is used in the Using Various RAD Module Elements, the result is two files. One, api_example_impl.c, holds the implementation of the GrabBag interface and data types it depends on, and should be compiled and linked with the GrabBag consumer. The other, api_example.h, exposes only the relevant symbols defined by api_example_impl.c and should be included by consumers of the GrabBag interface and its related types as shown in the following example.

Example 3-7 Showing a radadrgen-Generated C Header File

#include <rad/adr.h>
#include <rad/adr_object.h>
#include <rad/rad_modapi.h>

extern adr_type_t t__Mood;
extern adr_data_t e__Mood_IRREVERENT;
extern adr_data_t e__Mood_MAUDLIN;
extern adr_type_t t__SqrtError;
extern adr_type_t t__StringInfo;
extern adr_type_t t__MoodStatus;
extern adr_object_t interface_GrabBag;

A consumer who needs to create a MoodStatus structure indicating the mood is IRREVERENT and has changed, would issue the instructions shown in the following example.

Example 3-8 Consuming radadrgen-Generated Definitions

status = adr_data_new_struct(&t__MoodStatus);
adr_struct_set(status, "mood", e__Mood_IRREVERENT);
/* adr_struct_set(status, "mood", adr_data_new_enum_byname(&t__Mood, "IRREVERENT")); */
adr_struct_set(status, "changed", adr_data_new_boolean(B_TRUE));

if (!adr_data_verify(status, NULL, B_TRUE)) {
...

In addition to showing how to use the type definitions, this example also illustrates the multiple ways of referencing an enumerated value. Using the defined symbols is faster and can be checked by the compiler. The commented-out line uses adr_data_new_enum_byname which offers flexibility that could be useful in some situations but necessarily defers error checking until runtime. For example, if you mistype the value IRREVERENT, it would not be detected until the code is run. It is preferable to use the enumerated value symbols when possible.