Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Compilable C examples

Three complete programs, compiled against the committed header and linked to libair_base.so. The standalone sources live in docs/guides/abi-c/examples/ and are compiled (advisory) by scripts/build-docs.sh when cc and the cdylib are present — proof that the header and the lib are used exactly as described.

cargo build -p air-base-capi                  # → target/debug/libair_base.so

cc docs/guides/abi-c/examples/<example>.c \
   -I crates/air-base-capi/include \
   -L target/debug -lair_base \
   -Wl,-rpath,target/debug \
   -o <example>

See Getting started for the option details.

(a) UUID: new_v7to_hyphenatedparse

A full round-trip on a POD; nothing to free (stack buffer).

#include <stdio.h>
#include "air_base.h"

int main(void) {
  AirUuid u;
  if (air_uuid_new_v7(&u) != AIR_STATUS_OK) return 1;       /* `&u` borrowed +0 */

  char text[AIR_UUID_HYPHENATED_LEN];                       /* caller buffer (37) */
  if (air_uuid_to_hyphenated(&u, text, sizeof text) != AIR_STATUS_OK) return 1;
  printf("uuid v7 = %s\n", text);

  AirUuid back;
  if (air_uuid_parse(text, &back) != AIR_STATUS_OK) return 1;
  return 0;
}

Key points: text is your buffer (category 2); too small ⇒ AIR_STATUS_BUFFER_TOO_SMALL, nothing written. No air_*_free.

(b) Logging: openfieldsemitclose

The only example with owned handles (+1): it must free in the reverse order of acquisition.

#include <stdio.h>
#include "air_base.h"

int main(void) {
  AirLog *log = NULL;
  AirStatus st = air_log_open(NULL /* default journal */, &log);  /* +1 */
  if (st != AIR_STATUS_OK) {
    fprintf(stderr, "air_log_open: %s\n", air_status_message(st));
    return 1;
  }

  AirLogFields *fields = NULL;
  if (air_log_fields_new(&fields) != AIR_STATUS_OK) {  /* +1 */
    air_log_close(log);                                /* free what was acquired */
    return 1;
  }

  air_log_fields_add(fields, "REQUEST_ID", "abc-123"); /* fields borrowed-mut +0 */
  air_log_emit(log, AIR_LOG_LEVEL_INFO, "hello from C", fields); /* all +0 */

  air_log_fields_free(fields);   /* free the builder */
  air_log_close(log);            /* free the logger  */
  return 0;
}

Key points: open/new return owned handles → mandatory release (close/free). emit borrows everything (+0). On fields_new failure, the already-acquired log is freed before returning (no leak). AirLogFields is single-threaded (see Thread-safety).

(c) Time: nowelapsedas_secs_f64

Monotonic elapsed-time measurement on POD; reentrant, nothing to free.

#include <stdio.h>
#include "air_base.h"

int main(void) {
  AirInstant start;
  if (air_instant_now(&start) != AIR_STATUS_OK) return 1;  /* absolute value opaque */

  /* ... work to be measured ... */

  AirDuration d;
  if (air_instant_elapsed(&start, &d) != AIR_STATUS_OK) return 1;  /* saturated at 0 */

  double secs;
  if (air_duration_as_secs_f64(&d, &secs) != AIR_STATUS_OK) return 1;
  printf("elapsed = %.9f s (%lld s + %u ns)\n",
         secs, (long long)d.seconds, d.nanoseconds);
  return 0;
}

Key points: an AirInstant’s absolute value is opaque — only differences matter. air_instant_elapsed is saturated at zero if start is in the future (never a negative duration). Everything is local POD, hence reentrant.

What if cc is absent?

These examples are provided inline above (readable without compiling anything); the compilation by build-docs.sh is advisory: its absence never breaks the doc build. Conformance “like a real C consumer” is additionally verified by the crate’s ABI test (tests/abi/conformance.c).

Version française : Exemples C compilables.