3.8 Die Debug-Schnittstelle Korrektur einreichen Original anzeigen

Lua besitzt keine eingebauten Debug-Tools. Stattdessen bietet es eine spezielle Schnittstelle in Form von Funktionen und Hooks. Diese Schnittstelle erlaubt die Konstruktion verschiedener Arten von Debuggen, Profilern und anderen Tools, welche "interne Informationen" des Interpreters benötigen.

lua_Debug
typedef struct lua_Debug {
  int event;
  const char *name;           /* (n) */
  const char *namewhat;       /* (n) */
  const char *what;           /* (S) */
  const char *source;         /* (S) */
  int currentline;            /* (l) */
  int nups;                   /* (u) number of upvalues */
  int linedefined;            /* (S) */
  int lastlinedefined;        /* (S) */
  char short_src[LUA_IDSIZE]; /* (S) */
  /* private part */
  other fields
} lua_Debug;

Eine Struktur, um verschiedene Informationen über eine aktive Funktion abzulegen. lua_getstack befüllt lediglich den privaten Abschnitt dieser Struktur zur späteren Verwendung. Rufen Sie lua_getinfo auf, um die anderen Felder von lua_Debug mit nützlichen Informationen zu füllen.

Die Felder von lua_Debug haben folgende Bedeutung:

  • source: Wenn die Funktion durch eine Zeichenkette definiert wurde, ist source diese Zeichenkette. Wenn die Funktion in einer Datei definiert wurde, beginnt source mit einem '@', gefolgt vom Dateinamen.
  • short_src: Eine "druckbare" Version von source zur Verwendung in Fehlermeldungen.
  • linedefined: Die Zeilennummer, an der die Definition der Funktion beginnt.
  • lastlinedefined: Die Zeilennummer, an der die Definition der Funktion endet.
  • what: Die Zeichenkette "Lua", wenn die Funktion eine Lua-Funktion ist, "C" wenn es eine C-Funktion ist, "main" wenn es der Hauptteil des Chunks ist und "tail", wenn es sich um eine Datei mit Endrekursion handelt. Im letzten Fall besitzt Lua keine weiteren Informationen über die Funktion.
  • currentline: Die aktuelle Zeile, an der die gegebene Funktion ausgeführt wird. Wenn keine Zeileninformationen verfügbar sind, wird currentline auf -1 gesetzt.
  • name: Ein passender Name für die Funktion. Weil Funktionen unter Lua Werte erster Ordnung sind, haben diese keinen festen Bezeichner: Manche Funktionen können der Wert mehrerer globaler Variablen sein, während andere lediglich in einem Tabellenfeld gespeichert sind. Die lua_getinfo-Funktion prüft, wie die Funktion aufgerufen wurde, um einen passenden Namen zu finden. Falls kein Name gefunden werden konnte, wird name auf NULL gesetzt.
  • namewhat: Beschreibt das name-Feld. Der Wert von namewhat kann – entsprechend der aufgerufenen Funktion – "global", "local", "method", "field", "upvalue" oder "" (die leere Zeichenkette) sein. (Lua verwendet die leere Zeichenkette, wenn keine andere Option zuzutreffen scheint.)
  • nups: Die Anzahl gebundener Variablen der Funktion.
lua_gethook
lua_Hook lua_gethook(lua_State *L);

Liefert die aktuelle Hook-Funktion.

lua_gethookcount
int lua_gethookcount(lua_State *L);

Liefert die aktuelle Anzahl Hooks.

lua_gethookmask
int lua_gethookmask(lua_State *L);

Liefert die aktuelle Hook-Maske.

lua_getinfo
int lua_getinfo(lua_State *L, const char *what, lua_Debug *ar);

Liefert Informationen über eine spezifische Funktion oder Funktionsaufruf.

Um Informationen über einen Funktionsaufruf zu erhalten, muss der Parameter ar ein gültiger Aktivierungsdatensatz, welcher zuvor durch einen Aufruf von lua_getstack gefüllt wurde, sein oder als Argument an einen Hook übergeben werden (s. lua_Hook).

Um Informationen über eine Funktion zu erhalten, legen Sie diese auf dem Stapelspeicher ab und beginnen die Zeichenkette what mit dem Zeichen '>'. (In diesem Fall entfernt lua_getinfo die Funktion vom Stapelspeicher.) Um beispielsweise zu erfahren, in welcher Zeile eine Funktion f definiert wurde, können Sie folgenden Code schreiben:

lua_Debug ar;
lua_getfield(L,LUA_GLOBALSINDEX,"f");  /* globales 'f' erhalten */
lua_getinfo(L,">S",&ar);
printf("%d\n",ar.linedefined);

Jedes Zeichen der Zeichenkette what wählt einige Felder der Struktur ar zur Befüllung aus, oder legt Werte auf dem Stapelspeicher ab:

  • 'n': Befüllt die Felder name und namewhat.
  • 'S': Befüllt die Felder source, short_src, linedefined, lastlinedefined und what.
  • 'l': Befüllt das Feld currentline.
  • 'u': Befüllt das Feld nups.
  • 'f': Legt auf dem Stapelspeicher die auf gegebener Ebene laufende Funktion ab.
  • 'L': Legt auf dem Stapelspeicher eine Tabelle ab, deren Indizes die Nummern der gültigen Zeilen der Funktion sind. (Eine gültige Zeile ist eine Zeile mit zugehörigem Code, d. h. eine Zeile, in welcher Sie einen Haltepunkt setzen können. Nicht-gültige Zeilen beinhalten leere Zeilen und Kommentare.)

Diese Funktion liefert im Fehlerfall 0 (beispielsweise im Falle einer ungültigen Option für what).

lua_getlocal
const char *lua_getlocal(lua_State *L, lua_Debug *ar, int n);

Liefert Informationen über eine lokale Variable eines gegebenen Aktivierungsdatensatzes. Der Parameter ar welcher zuvor durch einen Aufruf von lua_getstack gefüllt wurde, sein oder als Argument an einen Hook übergeben werden (s. lua_Hook). Der Index n wählt die lokale Variable zur Untersuchung aus (1 ist der erste Parameter oder aktive lokale Variable usw., bis hin zur letzten aktiven lokalen Variable). lua_getlocal legt den Wert der Variablen auf dem Stapelspeicher ab und liefert dessen Name.

Variablen-Bezeichner, welche mit '(' (geöffnete Klammer) beginnen repräsentieren interne Variablen (Laufvariablen, temporäre Variablen und lokale C-Funktionsvariablen).

Liefert NULL (und legt nichts ab), wenn der Index größer als die Anzahl aktiver lokaler Variablen ist.

lua_getstack
int lua_getstack(lua_State *L, int level, lua_Debug *ar);

Liefert Informationen über den Laufzeit-Stapelspeicher des Interpreters.

Diese Funktion befüllt Teile einer lua_Debug-Struktur mit einer Identifikation des Aktivierungsdatensatzes der auf gegebener Ebene ausgeführten Funktion. Level 0 ist die aktuell laufende Funktion und Level n+1 ist die Funktion, welche Ebene n aufgerufen hat. Wenn keine Fehler auftreten, liefert lua_getstack 1; wenn sie mit einem höheren Level als die Stapelspeicher-Tiefe aufgerufen wird, liefert sie 0.

lua_getupvalue
const char *lua_getupvalue(lua_State *L, int funcindex, int n);

Liefert Informationen über die gebundenen Variablen eines Closures. (Bei Lua-Funktionen sind gebundene Variablen externe lokale Variablen, welche von der Funktion genutzt werden und konsequenterweise in deren Closure eingebunden werden.) lua_getupvalue erwartet den Index n einer gebundenen Variable, legt deren Wert auf dem Stapelspeicher ab und liefert ihren Namen. funcindex zeigt auf den Closure auf dem Stapelspeicher. (Gebundene Variablen haben keine bestimmte Ordnung, da diese über die ganze Funktion aktiv sind. Deshalb sind diese willkürlich nummeriert.)

Liefert NULL (und legt nichts ab), wenn der Index größer als die Anzahl gebundener Variablen ist. Diese Funktion verwendet für C-Funktionen die leere Zeichenkette "" als Name für alle gebundenen Variablen.

lua_Hook
typedef void (*lua_Hook)(lua_State *L, lua_Debug *ar);

Typ zum Debuggen von Hook-Funktionen.

Wann immer ein Hook aufgerufen wird, wird das Feld event dessen ar-Argument auf das spezifische Ereignis gesetzt, welches den Hook ausgelöst hat. Lua identifiziert diese Ereignisse mit den folgenden Konstanten: LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKTAILRET, LUA_HOOKLINE und LUA_HOOKCOUNT. Darüber hinaus wird für Zeilen-Ereignisse ebenso das Feld currentline gesetzt. Um den Wert irgendeines anderen Feldes von ar zu erhalten, muss der Hook lua_getinfo aufrufen. Rückgabe-Ereignisse können LUA_HOOKRET (der normale Wert) oder LUA_HOOKTAILRET sein. In letzterem Fall simuliert Lua eine Rückgabe von einer Funktion, welche eine Endrekursion durchführte; in diesem Fall ist es nutzlos, lua_getinfo aufzurufen.

Während Lua Hooks ausführt, unterbindet es andere Aufrufe von Hooks. Falls ein Hook also Lua anweist, eine Funktion oder einen Chunk auszuführen, erfolgt diese Ausführung ohne jegliche Aufrufe von Hooks.

lua_sethook
int lua_sethook(lua_State *L, lua_Hook f, int mask, int count);

Setzt die Hook-Funktion zum Debuggen.

Das Argument f ist die Hook-Funktion. mask gibt an, bei welchen Ereignissen der Hook aufgerufen wird: Die Angabe erfolgt durch ein bitweises ODER der Konstanten LUA_MASKCALL, LUA_MASKRET, LUA_MASKLINE und LUA_MASKCOUNT. Das count-Argument kommt nur zur Geltung, wenn die Maske LUA_MASKCOUNT beinhaltet. Für jedes Ereignis wird der Hook wie folgt aufgerufen:

  • Der "call"-Hook: wird aufgerufen, wenn der Interpreter eine Funktion aufruft. Der Hook wird direkt nach dem Betreten der Funktion aufgerufen, bevor die Funktion ihre Argumente erhält.
  • Der "return"-Hook: wird aufgerufen, wenn der Interpreter aus einer Funktion zurückkehrt. Der Hook wird direkt vor dem Verlassen der Funktion aufgerufen. Sie haben keinen Zugriff auf die von der Funktion zurückgelieferten Werte.
  • Der "line"-Hook: wird aufgerufen, wenn der Interpreter dabei ist, eine neue Zeile Code zu starten, oder wenn er in den Code zurückspringt (auch in die gleiche Zeile). (Dieses Ereignis findet nur statt, während Lua eine Lua-Funktion ausführt.)
  • Der "count"-Hook: wird aufgerufen, nachdem der Interpreter eine count-Anweisung ausführt. (Dieses Ereignis findet nur statt, während Lua eine Lua-Funktion ausführt.)

Ein Hook wird durch das Setzen von mask auf Null deaktiviert.

lua_setlocal
const char *lua_setlocal(lua_State *L, lua_Debug *ar, int n);

Setzt den Wert einer lokalen Variablen des gegebenen Aktivierungsdatensatzes. Die Parameter ar und n verhalten sich wie bei lua_getlocal (s. lua_getlocal). lua_setlocal weist der Variablen den Wert oben auf dem Stapelspeicher zu und liefert deren Name. Die Funktion entfernt auch den Wert vom Stapelspeicher.

Liefert NULL (und entfernt nichts), wenn der Index größer als die Anzahl aktiver lokaler Variablen ist.

lua_setupvalue
const char *lua_setupvalue(lua_State *L, int funcindex, int n);

Setzt den Wert der gebundenen Variablen eines Closures. Diese Funktion weist den Wert der oben auf dem Stapelspeicher abgelegten gebundenen Variablen zu und liefert deren Namen. Sie entfernt diesen Wert auch vom Stapelspeicher. Die Parameter funcindex und n verhalten sich wie bei lua_getupvalue (s. lua_getupvalue).

Liefert NULL (und entfernt nichts), wenn der Index größer als die Anzahl gebundener Variablen ist.