Inhaltsverzeichnis

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);
}

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.

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