====== std.res — eingebettete Ressourcen ======
''import std.res;''
Zugriff auf Dateien, die mit ''@resource("name", "pfad")'' **ins Erzeugnis eingebettet** wurden — über ihren Namen, zur Laufzeit. Das Gegenstück zu Delphis ''.res'': Bilder, Schriften, Vorlagen oder Konfigurationsvorgaben liegen im Programm selbst, nicht daneben im Dateisystem.
→ [[lyx_-_programmiersprache:sprache:attributes-pragmas#resource_und_embed|@resource und @embed]] · [[lyx_-_programmiersprache:units|Standard Library]] · [[https://github.com/SEOLizer/LyX-Compiler/issues/1961|#1961]]
----
===== 1. Einbetten und finden =====
unit main;
@resource("splash", "assets/splash.lyxi");
@resource("hilfe", "assets/hilfe.txt");
import std.res;
import std.io;
import std.string;
fn main(): int64 {
var bild: pchar := ResFind("splash");
var n: int64 := ResLen("splash");
PrintLn(StrConcat("Groesse: ", IntToStr(n)));
PrintLn(StrConcat("Inhalt: ", bild));
return 0;
}
Groesse: 16
Inhalt: SPLASH-BYTES-123
''@resource'' steht **auf Unit-Ebene**, nicht in einer Funktion. Der Pfad wird **relativ zur Quelldatei** aufgelöst, nicht zum Arbeitsverzeichnis — ein Programm lässt sich also aus jedem Verzeichnis übersetzen.
----
===== 2. Funktionen =====
^ Signatur ^ Zweck ^
| ''ResCount(): int64'' | Zahl der eingebetteten Ressourcen; ''0'', wenn keine vorhanden |
| ''ResFind(name: pchar): pchar'' | Zeiger auf die Bytes, oder ''0'' bei unbekanntem Namen |
| ''ResLen(name: pchar): int64'' | Länge in Byte, oder ''0'' |
| ''ResIndex(name: pchar): int64'' | Position in der Tabelle, oder ''-1'' |
| ''ResName(i: int64): pchar'' | Name des Eintrags ''i'' |
| ''ResBytesAt(i: int64): pchar'' | Bytes des Eintrags ''i'' |
| ''ResSizeAt(i: int64): int64'' | Länge des Eintrags ''i'' |
Damit lässt sich der Bestand auch **durchlaufen** — etwa für ein Werkzeug, das zeigt, was in einem Programm steckt:
var i: int64 := 0;
while (i < ResCount()) {
PrintLn(StrConcat(ResName(i), StrConcat(" ", IntToStr(ResSizeAt(i)))));
i := i + 1;
}
----
===== 3. Aufbau der Tabelle =====
Die Tabelle liegt im **Datensegment** und wird über das Builtin ''GetResTable()'' erreicht — dasselbe Muster wie ''GetEnvBlock'' ([[https://github.com/SEOLizer/LyX-Compiler/issues/1677|#1677]]): der Codegen kennt die Adresse, ''std/res.lyx'' rechnet in Lyx weiter. Damit ist die Bibliotheksseite lesbarer Lyx-Code und kein Compiler-Interna.
[0] Anzahl der Einträge
[1 + i*4 + 0] Zeiger auf den Namen (NUL-terminiert)
[1 + i*4 + 1] Länge des Namens
[1 + i*4 + 2] Zeiger auf die Bytes
[1 + i*4 + 3] Anzahl der Bytes
''GetResTable()'' liefert ''0'', wenn das Programm keine einzige ''@resource''-Angabe trägt. **Jede Funktion dieser Unit fängt diesen Fall ab** — ein Programm ohne Ressourcen bekommt ''ResCount() = 0'' und keinen Absturz.
----
===== 4. Fallstricke =====
* **Binärdaten sind nicht nullterminiert.** ''ResFind'' liefert einen ''pchar'', aber die Bytes stammen aus der Datei: enthält sie ein Nullbyte, endet jede Zeichenkettenfunktion dort. Die Länge kommt aus ''ResLen'', nicht aus ''StrLen'' — gemessen: eine Datei mit ''A\0B\0C'' meldet korrekt ''5''.
* **Der Name ist frei wählbar** und hat nichts mit dem Dateinamen zu tun. Zwei Ressourcen mit demselben Namen sind nicht sinnvoll; gesucht wird der erste Treffer.
* **Fehlt die Datei, bricht die Übersetzung ab**: ''error: @resource: Datei nicht lesbar: ''. Das ist Absicht — eine fehlende Ressource fällt beim Bauen auf, nicht beim Kunden.
* **''@resource'' wirkt über Unit-Grenzen.** Eine importierte Unit darf eigene Ressourcen mitbringen; sie landen in derselben Tabelle und sind über ihren Namen erreichbar.
**Nur ''%%--%%target=x86_64''.** Auf dem IR-Weg (''lyxos'', ''arm64'', ''riscv'', ''xtensa'') bricht die Übersetzung ab:
lyxc: @resource ist bisher nur mit --target=x86_64 umgesetzt.
Die Ressourcentabelle besteht aus Zeigern in den Datenbereich; auf dem
IR-Weg gibt es dafuer bisher nur die nullterminierte
Zeichenkettentabelle (siehe #1968).
Für einzelne Dateien geht dort ''@embed'' — bei **Textdateien**.
----
===== 5. Abgrenzung zu @embed =====
^ ^ ''@embed("pfad")'' ^ ''@resource("name", "pfad")'' ^
| Auflösung | zur **Übersetzungszeit**, der Pfad steht im Quelltext | zur **Laufzeit**, über den Namen |
| Ergebnis | Zeiger auf die Bytes (''@embed_len'' liefert die Größe) | Eintrag in einer benannten Tabelle |
| Auflisten möglich | nein | ja, über ''ResCount''/''ResName'' |
| Name zur Laufzeit wählbar | nein | ja |
| Zielplattformen | auch IR-Ziele (Textdateien) | nur x86-64 |
''@embed'' ist der kürzere Weg, wenn genau eine Datei an genau einer Stelle gebraucht wird:
var s: pchar := @embed("assets/hilfe.txt");
var n: int64 := @embed_len("assets/hilfe.txt");
**Warum ein Zeiger und kein ''[N]uint8''-Feld:** Lyx legt Felder mit **acht Byte je Element** ab, auch bei ''uint8''. Ein eingebettetes 1-MB-Bild bräuchte damit 8 MB im Erzeugnis. Die Bytes liegen deshalb **gepackt** im Datensegment, und ''@embed'' liefert die Adresse. Gelesen wird mit ''peek8'', wie bei jedem anderen Bytepuffer.
----
Letzte Aktualisierung: 2026-09-05 — Seite neu angelegt; erhoben aus ''std/res.lyx'' und ''src/parser.lyx'' ([[https://github.com/SEOLizer/LyX-Compiler/issues/1961|#1961]] Stufe 1 und 2), alle Beispiele gegen lyxc 1.2.2D übersetzt und ausgeführt.
===== Ressourcen in einer ''.lyu'' =====
Seit [[https://github.com/SEOLizer/LyX-Compiler/issues/1971|#1971]] trägt auch das ''.lyu''-Format eingebettete Ressourcen: der Abschnitt steht am Ende der Datei, der Offset im bisher reservierten Feld des Kopfes. Die Version bleibt 2 — ein Leser, der den Abschnitt nicht kennt, hört nach der Symboltabelle auf und liest die Datei unverändert.
''%%--%%unit-info'' listet die Ressourcen mit Name und Größe. Das ist die Stelle, an der sich **ohne Übersetzen** nachsehen lässt, was eine Bibliothek mitbringt.
Die Länge steht ausdrücklich in der Datei und nicht als Nullterminierung: eine Ressource ist eine Binärdatei und darf Nullbytes tragen — genau daran ist die Zeichenkettentabelle des IR-Wegs gescheitert ([[https://github.com/SEOLizer/LyX-Compiler/issues/1968|#1968]]).
> **Der Import daraus fehlt noch.** Eine ''.lyu'' trägt die Ressourcen zwar, aber eine importierende Übersetzung übernimmt sie nicht — das hängt an [[https://github.com/SEOLizer/LyX-Compiler/issues/2014|#2014]], solange die ''.lyu'' eine reine Namensliste ist. Offen sind ebenso die IR-Ziele und das LBF-Format.