Open Source im professionellen Einsatz
Linux-Magazin 03/2015
© Iurii Kovalenko, 123RF

© Iurii Kovalenko, 123RF

Lua- und C-Code mischen

Mond an Erde

Lua ist klein, schlank und vor allem schnell. Nicht zuletzt deshalb dient die Skriptsprache in vielen Anwendungen und Spielen als Vorlage und Einstieg. Dank der mitgebrachten C-Schnittstelle lässt sich der portugiesische Mond spielend leicht auch in eigene C-Programme integrieren.

716

Um von einem C-Programm aus ein Lua-Skript anzuwerfen, binden Entwickler zunächst die im Lua-Paket mitgelieferten Header »lua.h« und »lauxlib.h« ein, »lua.h« enthält dabei die von Lua bereitgestellten C-Funktionen. Deren Namen beginnen grundsätzlich mit »lua_« . Der Header »lauxlib.h« holt ein paar Hilfsfunktionen hinzu, die dem Programmierer etwas Schreibarbeit abnehmen. Die Namen aller Hilfsfunktionen beginnen mit dem Kürzel »luaL_« .

Sind die passenden »#include« -Anweisungen geschrieben, erstellt der C-Entwickler einen Lua-Interpreter:

lua_State *mystate = luaL_newstate();

Die Datenstruktur »lua_State« kapselt den kompletten Zustand (State) eines Lua-Interpreters. Auf diese Weise lassen sich mehrere unabhängige Lua-Interpreter gleichzeitig anwerfen. Wenn die Funktion jedoch den Lua-State nicht erstellen konnte, gibt sie »NULL« zurück – etwa dann, wenn nicht genügend Speicher vorhanden war.

Panik? Mach einfach!

Die Hilfsfunktion »luaL_newstate()« richtet zudem im Hintergrund eine Panik-Funktion ein, die bei einem Fehler eine entsprechende Meldung auf die Standardausgabe schreibt. Ein Lua-Skript führt jetzt die Funktion »luaL_dofile()« aus, die neben einem Zeiger auf den Lua-State lediglich den Dateinamen des Skripts erwartet:

luaL_dofile(mystate, "./beispiel.lua");

Alternativ legt der C-Programmierer das Lua-Skript in einem String ab. Das ist besonders dann nützlich, wenn es nur einen einzigen Lua-Befehl auszuführen gilt. Die Ausführung übernimmt die Funktion »luaL_dostring()« , die einfach den entsprechenden String mit dem Lua-Code übergeben bekommt:

luaL_dostring(mystate, "print(\"Hallo\")");

Dieser Beispiel-Befehl hätte aber keine Folgen, hier also kein »Hallo« ausgegeben. Der simple Grund: Der neu erzeugte Lua-Interpreter enthält standardmäßig keine Bibliotheken, womit aber auch das viel genutzte »print« fehlt.

Alle Standardbibliotheken auf einen Schlag lädt die Hilfsfunktion »luaL_openlibs(mystate);« . Trotz ihres Namens ist sie nicht im Header »lauxlib.h« definiert, sondern in einem eigenen namens »lualib.h« . Diesen dritten Header müssen C-Entwickler folglich ebenfalls noch einbinden.

Listing 1 zeigt ein Beispielprogramm, das einen Lua-Interpreter erstellt und dann das Lua-Skript in der Datei »beispiel.lua« ausführt. Bei der Übersetzung des C-Programms muss man lediglich die Lua-Bibliothek hinzulinken (Abbildung 1).

Listing 1

Lua-Skript aus C-Programm starten

01 #include "lua.h"
02 #include "lauxlib.h"
03
04 main()
05 {
06   lua_State *mystate = luaL_newstate();
07   luaL_openlibs(mystate);
08   luaL_dofile(mystate, "./beispiel.lua");
09   lua_close(mystate);
10 }
Abbildung 1: Bei der Übersetzung muss der Programmierer lediglich die (statische) Lua- und die Mathematik-Bibliothek hinzulinken. Sofern er die Lua-Bibliotheken nutzt, kommt noch die libdl hinzu.

Stapelweise

Die Kommunikation zwischen Lua-Skript und C-Programm erfolgt über einen Stack. Möchte der C-Entwickler eine Funktion in einem Lua-Skript aufrufen, legt er zunächst den Namen der Lua-Funktion auf den Stack und packt dann nacheinander die von der Funktion benötigten Parameter obendrauf. Anschließend bittet der Entwickler den Lua-Interpreter um die Ausführung. Listing 2 zeigt dafür ein Beispiel: Es ruft die im Lua-Skript »plus.lua« definierte Funktion »plus()« auf, die einfach zwei Zahlen addiert.

Listing 2

Neuen Interpreter anlegen

01 #include <stdio.h>
02 #include "lua.h"
03 #include "lauxlib.h"
04 #include "lualib.h"
05
06 int main (int argc, char *argv[])
07 {
08    lua_State *mystate = luaL_newstate(); // Neuer Interpreter
09    luaL_openlibs(mystate); // Bibliotheken laden
10    luaL_dofile(mystate, "./plus.lua"); // Skript laden
11
12    lua_getglobal(mystate, "plus"); // Name der Funktion auf den Stack
13   lua_pushinteger(mystate, 7); // Erster Parameter
14   lua_pushinteger(mystate, 5); // Zweiter Parameter
15
16   lua_pcall(mystate, 2, 1, 0); // Funktion ausführen
17   int ergebnis = lua_tointeger(mystate, -1); // Ergebnis vom Stack
18
19   printf("Ergebnis: %d\n", ergebnis);
20   lua_close(mystate);
21 }

Nachdem Zeile 8 einen neuen Interpreter angelegt hat, lädt die Funktion »luaL_dofile()« das Skript. Da das C-Programm die Funktion »plus()« aufrufen möchte, schiebt danach »lua_getglobal()« diesen Namen auf den Stack.

Die Funktion »plus()« erwartet zwei Zahlen. Beide Zahlen packt »lua_pushinteger()« nacheinander auf den Stack, im Beispiel sind das die Zahlen »5« und »7« . Anschließend ruft «lua_pcall()» die Lua-Funktion auf. Dazu benötigt « lua_pcall()» den Lua-State und die Anzahl der auf den Stack geschobenen Werte, im Beispiel waren das die beiden zu addierenden Zahlen.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 3 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

comments powered by Disqus

Stellenmarkt

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.