5.3 Module Korrektur einreichen Original anzeigen

Die Paketbibliothek bietet grundsätzliche Funktionen zum Laden und Erstellen von Modulen in Lua. Sie exportiert zwei ihrer Funktionen direkt in die globale Umgebung: require und module. Alles andere wird in eine Tabelle package exportiert.

module(name[,···])

Erstellt ein Modul. Falls sich eine Tabelle unter package.loaded[name] befindet, ist diese Tabelle das Modul. Wenn andernfalls eine globale Tabelle t mit dem gegebenen Namen existiert, ist diese Tabelle das Modul. Andernfalls wird eine neue Tabelle t erzeugt und als Wert des globalen name sowie package.loaded[name] gesetzt. Diese Funktion initialisiert auch t._NAME mit dem gegebenen Namen, t._M mit dem Modul (t selbst) und t._PACKAGE mit dem Paketnamen (der komplette Modulname ohne die letzte Komponente; s. u.). Schließlich setzt module t als neue Umgebung der aktuellen Funktion und den neuen Wert von package.loaded[name], so dass require t zurückliefert.

Falls name ein Kompositum ist (d. h. einer mit per Punkt getrennten Komponenten), erzeugt module Tabellen für jede Komponente (oder benutzt diese erneut, falls sie bereits existieren). Ist name beispielsweise a.b.c, dann speichert module die Tabelle im Feld c des Feldes b des globalen a.

Diese Funktion kann optionale options nach dem Modulnamen erhalten, wobei jede Option eine Funktion ist, welche auf das Modul angewendet wird.

require(modname)

Lädt das angegebene Modul. Die Funktion beginnt mit einer Suche in der package.loaded-Tabelle um herauszufinden, ob modname bereits geladen ist. Wenn das der Fall ist, liefert require den unter package.loaded[modname] gespeicherten Wert. Andernfalls versucht es einen Loader für das Modul zu finden.

Um einen Loader zu finden, wird require durch das package.loaders-Feld geführt. Durch das Verändern dieses Feldes können wir beeinflussen, wie require nach einem Modul sucht. Die folgende Erklärung basiert auf der Standardkonfiguration für package.loaders.

Zuerst fragt require package.preload[modname] ab. Wenn dies einen Wert hat, ist dieser Wert (welcher eine Funktion sein sollte) der Loader. Andernfalls sucht require nach einem Lua-Loader durch den in package.path gespeicherten Pad. Wenn das ebenfalls fehlschlägt, sucht es nach einem C-Loader mit Hilfe des unter package.cpath gespeicherten Pfades. Falls dies ebenfalls fehlschläft, versucht sie einen All-in-One-Loader (s. package.loaders).

Sobald ein Loader gefunden wurde, ruft require den Loader mit dem einzelnen Argument modname auf. Wenn der Loader irgendeinen Wert liefert, weist require den zurückgelieferten Wert package.loaded[modname] zu. Falls der Loader keinen Wert liefert und keinen Wert an package.loaded[modname] zugewiesen hat, weist require dem Eintrag true zu. In jedem Fall liefert require den finalen Wert von package.loaded[modname].

Falls ein Fehler beim Laden oder Ausführen des Moduls auftritt oder kein Loader für das Modul gefunden werden kann, signalisiert require einen Fehler.

package.cpath

Der Pfad, welcher von require verwendet wird, um nach einem C-Loader zu suchen.

Lua initialisiert den C-Pfad package.cpath auf die gleiche Weise wie den Lua-Pfad package.path unter Verwendung der Umgebungsvariable LUA_CPATH oder einen luaconf.h definierten Standardpfad.

package.loaded

Eine Tabelle, welche von require genutzt wird um zu kontrollieren, welche Module bereits geladen sind. Wenn Sie ein Modul modname einbinden und package.loaded[modname] nicht "false" ist, liefert require einfach den dort gespeicherten Wert.

package.loaders

Eine Tabelle, welche von require verwendet wird, um zu steuern, wie Module geladen werden.

Jeder Eintrag in dieser Tabelle ist eine Searcher-Funktion. Um nach einem Modul zu suchen ruft require jeden der Searcher in aufsteigender Reihenfolge mit dem Modulnamen (das Argument, welches an require übergeben wurde) als einzigem Parameter auf. Die Funktion kann eine weitere Funktion zurückliefert (das Modul loader) oder eine Zeichenkette, welche erklärt, wieso das Modul nicht gefunden werden konnte (oder nil, falls es nichts zu sagen gibt). Lua initialisiert diese Tabelle mit vier Funktionen.

Der erste Searcher sucht einfach nach einem Loader in der package.preload-Tabelle

Der zweite Searcher sucht nach einem Loader in Form einer Lua-Bibliothek unter Verwendung des unter package.path gespeicherten Pfades. Ein Pfad ist eine Folge von durch Semikolon getrennte Templates. Bei jedem Template ersetzt der Searcher jedes Fragezeichen im Template durch filename, was der Modulname ist, wobei jeder Punkt durch den Separator des Dateisystems (so etwas wie "/" unter Unix) ersetzt wurde; anschließend wird versucht, den sich ergebenden Dateinamen zu öffnen. Wenn der Lua-Pfad beispielsweise der Zeichenkette …

"./?.lua;./?.lc;/usr/local/?/init.lua"

… entspricht, versucht die Suche nach einer Lua-Datei des Moduls foo die Dateien ./foo.lua, ./foo.lc und /usr/local/foo/init.lua zu öffnen (in dieser Reihenfolge).

Der dritte Searcher sucht nach einem Loader in Form einer C-Bibliothek unter Verwendung des unter package.cpath gespeicherten Pfades. Wenn der C-Pfad beispielsweise der Zeichenkette …

"./?.so;./?.dll;/usr/local/?/init.so"

… entspricht, versucht der Searcher für das Modul foo die Dateien ./foo.so, ./foo.dll und /usr/local/foo/init.so zu öffnen (in dieser Reihenfolge). Sobald eine C-Bibliothek gefunden wird, benutzt der Searcher zuerst eine Funktion zum dynamischen Linken, um die Anwendung mit der Bibliothek zu linken. Dann wird versucht, eine C-Funktion innerhalb der Bibliothek zu finden, welche als Loader verwendet werden kann. Der Bezeichner dieser C-Funktion ist die Zeichenkette "luaopen_", verknüpft mit einer Kopie des Modulnamens, wobei jeder Punkt durch einen Unterstrich ersetzt wird. Darüber hinaus wird, wenn der Bezeichner einen Bindestrich enthält, dieser inkl. dem ersten vorangehenden Präfx entfernt. Wenn der Modulname beispielsweise a.v1-b.c ist, wird der Funktionsname luaopen_b_c sein.

Der vierte Searcher versucht einen All-in-One-Loader. Dieser durchsucht den C-Pfad nach einer Bibliothek für den ersten Bezeichner des gegebenen Moduls. Wenn beispielsweise das Modul a.b.c eingebunden wird, wird nach einer C-Bibliothek für a gesucht. Wird diese gefunden, wird nach einer öffnenden Funktion für das Untermodul gesucht; in unserem Beispiel wäre das luaopen_a_b_c. Durch diese Vorgehensweise kann ein Paket mehrere C-Untermodule in einer Bibliothek beinhalten, wobei jedes Untermodul seine originale öffnende Funktion behält.

package.loadlib(libname,funcname)

Linkt das Host-Programm dynamisch mit der C-Bibliothek libname. Innerhalb dieser Bibliothek wird nach einer funcname-Funktion gesucht und diese Funltion als C-Funktion zurückgeliefert. (funcname muss demnach die Spezifikation erfüllen (s. lua_CFunction)).

Dies ist eine Low-Level-Funktion. Diese läuft völlig neben dem Paket- und Modulsystem. Im Gegensatz zu require führt diese keine Pfadsuche durch und fügt Erweiterungen nicht automatisch hinzu. libname musst der komplette Dateiname der C-Bibliothek sein, ggf. inklusive Pfad und Dateierweiterung. funcname muss der exakte von der C-Bibliothek exportierte Name sein (was vom benutzten C-Compiler und Linker abhängen kann).

Diese Funktion wird nicht von ANSI-C unterstützt. Insofern ist sie nur unter bestimmten Plattformen verfügbar (Windows, Linux, Mac OS X, Solaris, BSD und andere unixoide Systeme, welche den dlfcn-Standard unterstützen).

package.path

Der Pfad, welcher von require verwendet wird, um nach einem Lua-Loader zu suchen.

Zu Beginn initialisiert Lua diese Variable mit dem Wert der Umgebungsvariable LUA_PATH oder mit einem in luaconf.h definierten Standardpfad, falls die Umgebungsvariable nicht definiert ist. Jedes ";;" im Wert der Umgebungsvariable wird durch den Standardpfad ersetzt.

package.preload

Eine Tabelle zum Speicher von Loadern für spezifische Module (s. require).

package.seeall(module)

Setzt eine Metatabelle für module, dessen __index-Feld auf die globale Umgebung zeigt, so dass dieses Modul Werte aus der globalen Umgebung erben kann. Zur Verwendung als Option für die Funktion module.