Exemples C compilables
Trois programmes complets, compilés contre le header committé et liés à
libair_base.so. Les sources autonomes vivent dans
docs/guides/abi-c/examples/
et sont compilées (advisory) par scripts/build-docs.sh quand cc et la cdylib
sont présents — preuve que le header et la lib s’emploient exactement comme décrit.
Compiler & lier (rappel)
cargo build -p air-base-capi # → target/debug/libair_base.so
cc docs/guides/abi-c/examples/<exemple>.c \
-I crates/air-base-capi/include \
-L target/debug -lair_base \
-Wl,-rpath,target/debug \
-o <exemple>
Voir Mise en route pour le détail des options.
(a) UUID : new_v7 → to_hyphenated → parse
Round-trip complet sur un POD ; rien à libérer (buffer sur la pile).
#include <stdio.h>
#include "air_base.h"
int main(void) {
AirUuid u;
if (air_uuid_new_v7(&u) != AIR_STATUS_OK) return 1; /* `&u` emprunté +0 */
char text[AIR_UUID_HYPHENATED_LEN]; /* buffer appelant (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;
}
Points clés : text est votre buffer (catégorie 2) ; trop petit ⇒
AIR_STATUS_BUFFER_TOO_SMALL, rien écrit. Aucune air_*_free.
(b) Logging : open → fields → emit → close
Le seul exemple avec des handles possédés (+1) : il doit libérer dans l’ordre inverse de l’acquisition.
#include <stdio.h>
#include "air_base.h"
int main(void) {
AirLog *log = NULL;
AirStatus st = air_log_open(NULL /* journal par défaut */, &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); /* libère l'acquis */
return 1;
}
air_log_fields_add(fields, "REQUEST_ID", "abc-123"); /* fields emprunté-mut +0 */
air_log_emit(log, AIR_LOG_LEVEL_INFO, "hello depuis C", fields); /* tout +0 */
air_log_fields_free(fields); /* libère le builder */
air_log_close(log); /* libère le logger */
return 0;
}
Points clés : open/new rendent des handles possédés → libération obligatoire
(close/free). emit emprunte tout (+0). Sur l’échec de fields_new, on libère
le log déjà acquis avant de sortir (pas de fuite). AirLogFields est mono-thread
(cf. Thread-safety).
(c) Temps : now → elapsed → as_secs_f64
Mesure d’écoulement monotone sur des POD ; réentrant, rien à libérer.
#include <stdio.h>
#include "air_base.h"
int main(void) {
AirInstant start;
if (air_instant_now(&start) != AIR_STATUS_OK) return 1; /* valeur absolue opaque */
/* ... travail à mesurer ... */
AirDuration d;
if (air_instant_elapsed(&start, &d) != AIR_STATUS_OK) return 1; /* saturé à 0 */
double secs;
if (air_duration_as_secs_f64(&d, &secs) != AIR_STATUS_OK) return 1;
printf("écoulé = %.9f s (%lld s + %u ns)\n",
secs, (long long)d.seconds, d.nanoseconds);
return 0;
}
Points clés : la valeur absolue d’un AirInstant est opaque — seules les
différences ont un sens. air_instant_elapsed est saturé à zéro si start
est dans le futur (jamais de durée négative). Tout est POD local, donc réentrant.
Et si cc est absent ?
Ces exemples sont fournis en bloc ci-dessus (lisibles sans rien compiler) ; la
compilation par build-docs.sh est advisory : son absence ne casse jamais le
build de la doc. La conformité « comme un vrai consommateur C » est par ailleurs
vérifiée par le test ABI de la crate (tests/abi/conformance.c).
English version: Compilable C examples.