====== Lyx – Foreign Function Interface (FFI) ====== Das **Foreign Function Interface (FFI)** erlaubt es Lyx-Programmen, Funktionen aufzurufen, die in anderen Programmiersprachen (primär C) geschrieben wurden, und Daten mit ihnen auszutauschen. Dies ist notwendig für die Nutzung von System-APIs (POSIX, Win32) oder spezialisierten Mathematik-Bibliotheken. ===== 1. Externe Funktionen deklarieren (@extern) ===== Um eine C-Funktion aufzurufen, muss sie in Lyx deklariert werden. Das Attribut ''@extern'' teilt dem Compiler mit, dass die Implementierung nicht in Lyx vorliegt, sondern beim Linken in einer externen Objektdatei oder Bibliothek gesucht werden muss. // Deklaration der C-Funktion 'printf' aus der Standard-C-Lib @extern fn printf(format: pchar, val: int64): int32; fn main() { printf("Zahl aus C: %d\n", 42); } * **Linker-Hinweis**: Beim Kompilieren muss die entsprechende Bibliothek meist mitgelinkt werden (z. B. via CLI-Option oder Build-Skript). ===== 2. Datentyp-Mapping (Lyx <-> C) ===== Beim FFI ist es entscheidend, dass die Bit-Breiten der Typen übereinstimmen. ^ Lyx Typ ^ C Äquivalent ^ Beschreibung ^ | ''int8'' | ''int8_t'' / ''char'' | 8-Bit Ganzzahl | | ''int32'' | ''int32_t'' / ''int'' | 32-Bit Ganzzahl | | ''pchar'' | ''char*'' | Nullterminierter String-Pointer | | ''^void'' | ''void*'' | Generischer Pointer | | ''type S = struct'' | ''struct S'' | Strukturen (nutze [[#@packed]]) | ===== 3. Strukturen und Memory-Layout (@packed) ===== C-Compiler fügen oft "Padding" (Füllbits) zwischen Strukturfeldern ein, um den Zugriff zu beschleunigen. Lyx macht das standardmäßig auch. Wenn eine Hardware-Struktur oder eine C-Bibliothek ein exaktes Layout ohne Lücken erwartet, muss das Attribut ''@packed'' verwendet werden. @packed type CStruct = struct { id: uint8, // 1 Byte value: uint32 // 4 Bytes, direkt nach id ohne 3 Bytes Padding } ===== 4. Strings und Speicher-Besitz ===== Ein häufiger Fehler im FFI ist das Management von Strings. * **Lyx zu C**: Ein ''pchar'' in Lyx ist bereits ein nullterminierter String-Pointer und kann direkt an C-Funktionen übergeben werden. * **C zu Lyx**: Wenn eine C-Funktion einen Pointer zurückgibt, muss geklärt werden, wer den Speicher freigibt (''free()'' in C vs. ''dispose'' in Lyx). @extern fn get_os_username(): pchar; fn print_user() { let name: pchar := get_os_username(); PrintStr(name); // Achtung: Wenn C den Speicher allokiert hat, darf Lyx ihn nicht disposen! } ===== 5. Callback-Funktionen ===== Lyx kann Funktionspointer an C übergeben, damit C Lyx-Code aufruft (Callbacks). Dies ist bei GUI-Bibliotheken oder asynchronen Treibern üblich. type TimerCallback = fn(delta: f64); @extern fn SetTimer(ms: int32, callback: TimerCallback); fn MyTimerTick(delta: f64) { PrintStr("Tick!"); } fn start() { SetTimer(1000, MyTimerTick); } ===== 6. Sicherheitshinweis (Unsafe) ===== FFI-Aufrufe gelten in Lyx grundsätzlich als **unsafe**, da der Compiler nicht prüfen kann, was innerhalb der C-Bibliothek passiert (z. B. Speicherverletzungen oder Null-Pointer-Dereferenzierung). > **DO-178C Hinweis:** > In hochkritischen Systemen (DAL A/B) müssen FFI-Schnittstellen durch "Wrapper" gekapselt werden, die Eingangsdaten validieren, bevor sie an die externe C-Funktion gereicht werden.