Lua C++ Interface und Konsole
Verfasst: 1. Januar 2012 17:01
Hallo Leute,
ich möchte euch ein "kleines" Hilfsmittel vorstellen, das ich zusammengestellt habe, um mir die Integration einer Lua Schnittstelle mit Klassenbindung zu erleichtern. Wer das mal gemacht hat, weiß, daß das eine ziemliche Frickelei sein kann. Um das hinzubiegen muß man sich in der Materie schon ganz schön auskennen, weswegen es eigentlich nicht wirklich Alltagstauglich ist.
Grundlage bildet zunächst Luna, mit dem sich C++ Bindings realisieren lassen. Darauf setzt ein Wrapper für Lua auf (MIGHTY:Script von Neil Lalonde), den ich für meine Zwecke etwas erweitert habe. Im Endeffekt reduziert sich der Aufwand für einen Script-Aufruf (neben der einmaligen, kurzen Initialisierung des Wrappers) auf:
Durch den Wrapper lassen sich auch Parameter direkt an das Script und zurück übergeben:
Eine Basisklasse "CScriptObject" stellt den Rumpf für jede exportierte Klasse bereit. Man registriert eine davon abgeleitete Klasse mittels eines Macro als exportiert:
oder, man benutzt folgendes Macro, womit gleich eine Instanz (hier 'app') der exportierten Klasse angelegt wird, mit der man global arbeiten kann:
ein Aufruf einer Funktion dieser Klasse sieht dann im Script so aus:
der Code dieser Funktion sieht zB so aus:
womit wir bei der Konsole wären. Dies ist ein simpler Dialog mit einem Textfenster und einer Eingabezeile. Man kann sie als globale Ausgabemöglichkeit benutzen und Befehle an den Script Handler geben, zB ein Script ausführen:

Der Clou daran: hat man seine exportierte Klasse mit dem Macro LUNA_REGISTER_WITHOBJECT angelegt, steht die Instanz des Objektes mit seinen Funktionen in der Eingabezeile mit Codevervollständigung zur Verfügung.

Zudem besitzt jede Klasse vom Typ "CScriptObject" eine Funktion, um alle ihre exportierten Funktionen mit Name und Parameter in die Konsole auszugeben (automatisch geht das natürlich nicht, man muß jede Funktion einmal in ein Array klimpern, damit der Completer sie kennt).

Das ganze System ist modular gehalten, sodaß man eine bestehende Applikation damit ausrüsten kann. Die Konsole ist über ein Macro abschaltbar, sodaß auf Wunsch nur der ScriptHandler zur Verfügung steht. Außerdem kann man festlegen, ob bei einem Fehler im Script eine Exception ausgelöst, oder einfach nur der zugrundeliegende Fehler (zB in die Konsole) ausgegeben wird.
Damit erstmal genug. Falls sich jemand für das Thema interessiert, werde ich den Code zur Verfügung stellen (falls nicht, kann ich mir die Mühe sparen
), also bei Interesse einfach hier per Reply oder PM melden
ich möchte euch ein "kleines" Hilfsmittel vorstellen, das ich zusammengestellt habe, um mir die Integration einer Lua Schnittstelle mit Klassenbindung zu erleichtern. Wer das mal gemacht hat, weiß, daß das eine ziemliche Frickelei sein kann. Um das hinzubiegen muß man sich in der Materie schon ganz schön auskennen, weswegen es eigentlich nicht wirklich Alltagstauglich ist.
Grundlage bildet zunächst Luna, mit dem sich C++ Bindings realisieren lassen. Darauf setzt ein Wrapper für Lua auf (MIGHTY:Script von Neil Lalonde), den ich für meine Zwecke etwas erweitert habe. Im Endeffekt reduziert sich der Aufwand für einen Script-Aufruf (neben der einmaligen, kurzen Initialisierung des Wrappers) auf:
Code: Alles auswählen
bool x_ExecCode = pLuaHandler->Execute("scripts/testscript.lua", "TestFunction");Code: Alles auswählen
int i_ReturnValue;
pLuaHandler->LoadScriptFile("scripts/testscript.lua");
pLuaHandler->callFunction("TestFunctionParam", "s>i", "String zum Script", &ReturnValue);
Code: Alles auswählen
LUNA_REGISTER(CScriptApp, "CScriptApp");Code: Alles auswählen
LUNA_REGISTER_WITHOBJECT(CScriptApp, "CScriptApp", "app");\Code: Alles auswählen
app:SetString('This is a test')Code: Alles auswählen
int CScriptApp::SetString(lua_State *L) {
int nargs = lua_gettop(L);
if(nargs>=LUA_FIRST_PARAMETER)
{
// store the string
qstr_IntData = lua_tostring(L, LUA_FIRST_PARAMETER);
OUTPUT_TO_CONSOLE(qstr_IntData);
}
// clear stack
lua_pop( L, lua_gettop( L ) );
return 1;
}
Der Clou daran: hat man seine exportierte Klasse mit dem Macro LUNA_REGISTER_WITHOBJECT angelegt, steht die Instanz des Objektes mit seinen Funktionen in der Eingabezeile mit Codevervollständigung zur Verfügung.

Zudem besitzt jede Klasse vom Typ "CScriptObject" eine Funktion, um alle ihre exportierten Funktionen mit Name und Parameter in die Konsole auszugeben (automatisch geht das natürlich nicht, man muß jede Funktion einmal in ein Array klimpern, damit der Completer sie kennt).

Das ganze System ist modular gehalten, sodaß man eine bestehende Applikation damit ausrüsten kann. Die Konsole ist über ein Macro abschaltbar, sodaß auf Wunsch nur der ScriptHandler zur Verfügung steht. Außerdem kann man festlegen, ob bei einem Fehler im Script eine Exception ausgelöst, oder einfach nur der zugrundeliegende Fehler (zB in die Konsole) ausgegeben wird.
Damit erstmal genug. Falls sich jemand für das Thema interessiert, werde ich den Code zur Verfügung stellen (falls nicht, kann ich mir die Mühe sparen