====== 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.