Tutorial
Einbindung der Skriptsprache Lua
von nemored | Seite 4 von 4 |
Aufruf einer Skriptfunktion
Um eine spezielle Funktion des Skripts aufzurufen, ist etwas Vorarbeit nötig. Wir laden das Skript zuerst mit luaL_loadfile und rufen es mit lua_pcall auf. Warum diesmal nicht einfach wieder luaL_dofile? Ganz einfach: Das Skript wird nur aufgerufen, um im Folgenden auf die Funktion zugreifen zu können. Rückgabewerte des Skripts sind im Augenblick uninteressant und können unter Umständen sogar hinderlich sein. Deswegen legen wir beim Aufruf von lua_pcall fest, dass das Skript keine Rückgabewerte auf den Stack legt - es ist damit sichergestellt, dass der Stack anschließend noch leer ist.
Danach legen wir die gewünschte Funktion mittels lua_getglobal auf den Stack, gefolgt von den benötigten Parametern (lua_pushnumber oder entsprechende Funktionen). Der Aufruf erfolgt anschließend durch ein weiteres lua_pcall, diesmal jedoch zusammen mit der Angabe der Parameterzahl und der Anzahl der Funktions-Rueckgabewerte.
Dies soll anhand einer ggT-Berechnung (größter gemeinsamer Teiler) demonstriert werden. Da im Skript auf eine Funktion der mathematischen Bibliothek zugegriffen wird, müssen wieder die Standardbibliotheken geladen werden. Die Skript-Funktion erwartet zwei Eingabeparameter und gibt einen Wert zurück. Der zweite Aufruf von lua_pcall lautet also in diesem Fall:
lua_pcall(Lua, 2, 1, 0)
(wobei die abschließende 0 festlegt, dass keine gesonderte Fehlerfunktion definiert wird, sondern die Standardfehlerausgabe verwendet werden soll).
#INCLUDE ONCE "Lua/lua.bi"
#INCLUDE ONCE "Lua/lauxlib.bi"
#INCLUDE ONCE "Lua/lualib.bi"
DIM Lua AS lua_State PTR
DIM AS INTEGER m = 27, n = 36
Lua = luaL_newstate
luaL_openlibs(Lua)
' Skript laden
IF luaL_loadfile(Lua, "ggt.lua") ORELSE lua_pcall(Lua, 0, 0, 0) THEN
PRINT "Fehler: " & *lua_tostring(Lua, -1)
END
END IF
' Funktion vorbereiten und aufrufen
lua_getglobal(Lua, "ggT")
lua_pushnumber(Lua, m)
lua_pushnumber(Lua, n)
IF lua_pcall(Lua, 2, 1, 0) THEN
PRINT "Skriptfehler: " & *lua_tostring(Lua, -1)
END
END IF
PRINT "Der ggT von " & m & " und " & n & " ist ";
PRINT lua_tonumber(Lua, -1) & "."
SLEEP
Das Lua-Skript ggt.lua sieht folgendermaßen aus:
function ggT(n, m)
q = math.floor(n/m)
r = n - m * q
if r==0 then return m else return ggT(m,r) end
end
Aufruf einer Programmfunktion im Skript
Umgekehrt kann auch eine im Hauptprogramm definierte Funktion vom Skript aus aufgerufen werden. Dazu muss diese Funktion dem Skript lediglich über lua_register bekannt gemacht werden. Der folgende Quelltext ist weitgehend dem Beispielordner der FreeBASIC-Installation entnommen.
#INCLUDE ONCE "Lua/lua.bi"
#INCLUDE ONCE "Lua/lauxlib.bi"
#INCLUDE ONCE "Lua/lualib.bi"
FUNCTION minmax CDECL (BYVAL L AS lua_State PTR) AS LONG
DIM numpar AS INTEGER
DIM i AS INTEGER
DIM num AS DOUBLE
DIM maxnum AS DOUBLE
DIM minnum AS DOUBLE
' Anzahl der Parameter ermitteln
numpar = lua_gettop(L)
' Alle Parameter auslesen und auswerten
minnum = lua_tonumber(L, 1)
maxnum = lua_tonumber(L, 1)
FOR i = 1 TO numpar
' Parameter aus dem Stack holen
num = lua_tonumber(L, i)
IF num > maxnum THEN maxnum = num
IF num < minnum THEN minnum = num
NEXT i
' Ergebnis auf den Stack legen
lua_pushnumber(L, minnum)
lua_pushnumber(L, maxnum)
' Anzahl der Parameter zurueckgeben
RETURN 2
END FUNCTION
DIM Lua AS lua_State PTR
Lua = luaL_newstate
luaL_openlibs(Lua) ' Standardbibliotheken oeffnen laden (fuer 'print')
lua_register(Lua, "MinMax", @minmax) ' FB-Funktion fuer Lua registrieren
IF luaL_dofile(Lua, "minmax.lua") THEN
PRINT "Skriptfehler: " & *lua_tostring(Lua, -1)
END IF
lua_close Lua ' Lua-Status freigeben
SLEEP
Dazu die Skriptdatei minmax.lua:
Min, Max = MinMax(42, 2, 17, 33, 15, 1.5)
print("Lua: Min= ", Min, ", Max= ", Max, "\n")
Zusätzliche Informationen und Funktionen | |||||||
---|---|---|---|---|---|---|---|
|