api ist eine header-basierte Makro-Bibliothek, die C C++-ähnliche
Vorteile verschafft – zumindest was die Lesbarkeit angeht.
private/protected-Sichtbarkeit und überschreibbare callbacks machen
klassen-typische Kapselung und virtuelle Hooks ohne OOP-Overhead direkt im
Quelltext ausdrückbar. Keine Laufzeit, kein Overhead, rein C.
Ziel
C hat keine Sprachebenen-Sichtbarkeit wie C++ (private/protected) und
keine Features wie static virtuelle Hooks. api übersetzt genau diese
Lesbarkeits-Vorteile in Makros: Die Absicht („nur hier intern” vs.
„bibliotheksintern” vs. „Sicht für die Anwendung”) steht im Code, statt in
Konventionen versteckt zu sein. Es ist bewusst keine OOP-Schicht – nur
Marker, die der C-Preprozessor in bereits legalen C-Ausdruck übersetzt.
Makros
Makro
Expansion
Bedeutung
private
static
nur in der eigenen Übersetzungseinheit (this.c) sichtbar
protected
(leer)
Kennzeichnung „bibliotheksintern” in der Definition (*.c)
protected_import(type, function)
extern type function
Import einer geschützten Funktion in die Übersetzungseinheit
callback
(leer)
virtueller Callback, den die Anwendung liefert
callback_declaration(type, function)
extern type function __attribute__((weak))
voreinstellbare (weak) Callback-Deklaration des Moduls (*.h) – überschreibbar
Nutzung
#include <api/api.h>private void helfer(void) { /* nur in dieser .c */ }protected void kern(void) { /* bibliotheksintern */ }callback void app_hook(void); /* von der Anwendung definiert */callback_declaration(void, app_hook); /* weak-Default im Modul */
Der Aufrufer liest die Sichtbarkeit direkt aus dem Quelltext – derselbe
Lesekomfort wie private:/protected: in C++, ohne Klassen-OOP.
Nutzung im gui-Projekt (real)
gui (GTK-Widget-Bibliothek) nutzt alle drei Makros produktiv:
callback_declaration – jedes Widget-Modul deklariert eine weak
überschreibbare Hook:
Die Bibliothek ruft sie nur bei if (gui_gl != NULL) / if (gui_application != NULL).
Ohne starke Definition der Anwendung ist das weak-Symbol NULL; mit
Definition gewinnt die App. Effekt: „virtuell” wie in C++ – das
Bibliotheks-Skelett liefert den Ablauf (startup/activate/shutdown,
render/realize, click/toggle), die Anwendung liefert nur die Logik.
private – GTK-Signalhandler und interne Helfer sind private
(_gui_gl_render, _gui_button_clicked, _widgets_list_head, …):
sofort lesbar, was nur übersetzungseinheiten-intern ist.