2016-02-16 7 views
5

Ich habe eine Anwendung, die Lua-Skripte ausgeführt wird. Jedes Lua-Skript wird wahrscheinlich mehrmals ausgeführt. Einige Skripts können sogar jedes Mal ausgeführt werden, wenn eine Taste gedrückt wird.Lua - Reseting den Zustand eines Skripts ohne neuparsen es

würde ich diese Skripte wie zwischen jedem Durchlauf „Reset“ zu sein. Wenn ein Benutzer beispielsweise eine Variable Foo setzt, sollte Foo beim nächsten Mal nicht im Skript vorhanden sein, bis der Benutzer es erneut definiert.

Das Problem ist, dass, wenn ich ein solches Verhalten haben wollen, ich brauche ein neues lua_State jedes Mal zu erstellen, öffnen Sie dann die Bibliotheken in sie jedes Mal, und dann die Skript-Datei jedes Mal zu analysieren, die sehr unoptimized scheint.

die Bibliotheken Laden kann einen eher leichten Betrieb sein (ich nehme an), aber die Skripte Parsen ist wahrscheinlich nicht.

Gibt es eine Möglichkeit, den Status eines Lua-Skripts (d. H. Klare benutzercodedefinierte Variablen) zurückzusetzen, ohne einen neuen lua_State zu erstellen und die gesamte Lua-Skriptdatei zu reparieren? Ich möchte nur, dass die Skriptdateien beim Start der Anwendung einmal analysiert werden, da sie zur Laufzeit nicht geändert werden.

Vielen Dank. :)

EDIT: Ich habe dieses Thema gefunden, aber es ist nicht detailliert über das zu tun: http://lua-users.org/lists/lua-l/2006-01/msg00493.html

EDIT: lua_setfenv scheint, dass zusammenzuhängen. Ich werde ein bisschen mehr graben.

BEARBEITEN: Es scheint, als ob es nicht mehr lua_setfenv als von LUA 5.2 gibt. Da ich bin mit 5.3 würde ich die environement gesetzt hat (dh eine versteckte Tabelle nammed _ENV wo Variablen gespeichert sind), um das zu tun, und damit alles neu zu laden, das ist, was ich will nicht zu ...

+0

Sie können es Lua Seite tun vielleicht mit Koroutinen? – warspyking

Antwort

1

ich das letzte Mal in dieser Antwort aussah, war nicht, leider.

Sie müssen auch bedenken, dass die Lua-Bibliotheken aufrufen kann, dass Dateien öffnen kann, malloc() Speicher usw., und dass jede ‚Reset‘ muss mit dem Schließen dieser Dateien umgehen, dass der Speicher freigegeben werden kann, usw.

Als Alternative zum Zurücksetzen des Lua-Status können Sie Ihren Code einfach so organisieren, dass er nicht zurückgesetzt werden muss. Dies erfordert offensichtlich, dass der Lua-Code auf eine bestimmte Weise geschrieben wird. Eine Möglichkeit dazu wäre, darauf zu bestehen, dass Ihr Lua-Code vollständig (oder fast vollständig) in Funktionen enthalten ist und eine oder mehrere Funktionen für jede Aktion aufruft. Der Code außerhalb der Funktionen könnte (z. B.) eine Lua-Tabelle zurückgeben, die aus Referenzen zum Aufrufen bestimmter Eintrittspunkte besteht; Dies würde nur einmal aufgerufen werden. Die Funktion (en) würden, wenn sie aufgerufen werden, nach sich selbst aufräumen, einschließlich des Aufhebens von Bibliotheks-zugewiesenen Elementen, Öffnen von Dateien usw. Globale Variablen sollten vermieden werden (es sei denn, sie sind konstant). Wir verwenden diesen Ansatz erfolgreich, um sicherzustellen, dass Lua nur einmal analysiert wird, die Eintrittspunkte einmal bestimmt werden, aber relativ kleine Funktionen mit sehr geringem Aufwand sehr schnell aufgerufen werden können.

In den Kommentaren Sie vorgeschlagen, dass Sie lexikalisch den Lua-Code in einem Funktionsblock wickeln könnte.Ich denke, das ist weniger flexibel als der obige Ansatz und hat folgende Nachteile:

  • Sie verlieren die Möglichkeit, eine "einmalige init (zB zum Beispiel eine feste Konstante von der Festplatte zu lesen) zu tun

  • Sie riskieren unvorhersehbare Dinge, wenn ein Benutzer Einsätze (zB) ein nicht übereinstimmen end ... function B() in ihrem Code

  • Sie sich per Lua Zustand zu einem Einstiegspunkt beschränken.

Es bedeutet, dass der Lua-Code in einer anderen Art und Weise geschrieben werden muß (im Wesentlichen ist die Lua-Codierer den Code in Form Versorgung erforderlich). Ein möglicher Weg ist ein festes Framework, um dies zu tun und require im Code als Bibliotheken zu nennen. Ich habe diesen Ansatz nicht ausprobiert.

+0

Danke für Ihre Hilfe. Wenn einige Bibliotheken Ressourcen zuweisen, sollten diese Ressourcen beim Löschen aller Benutzervariablen nicht automatisch release/garbage gesammelt werden? Könnte ich einfach manuell alle Werte in _ENV vor dem Ausführen eines Skripts entfernen und etwas wie lua_settop (0) tun, um den Stapel zurückzusetzen? – Virus721

+0

Und eine weitere Frage, die mein Problem auf andere Weise lösen könnte: was ist, wenn alle vom Benutzer erstellten Variablen lokal definiert verwenden, und dann in eine Funktion vor Parsen es umhüllte der vorbereiteten? Wenn die Funktion enden würde, wären alle Einheimischen zerstört, richtig? – Virus721

+0

@ Virus721 - sicher, wenn das Programm effektiv selbst zurückgesetzt (oder eher nicht zurückgesetzt werden muss), würde das funktionieren. Was wir tun, ist sehr ähnlich zu dem, dass auf globaler Ebene ist es nur einen Zeiger auf eine Funktion zurückkehrt (IIRC - lange Zeit, da ich sie geschaut haben), und diese Funktion sollte sich in einer Weise auszuführen, die aufräumt nach selbst. Aber ich bin nicht sicher, ob es eine Möglichkeit gibt, ein * beliebiges * Lua-Programm von außerhalb des Programms zurückzusetzen. Ich glaube nicht, dass der Ansatz "alle Benutzervariablen löschen" fliegen wird, da Sie möglicherweise wissen müssen, in welcher Reihenfolge sie gelöscht werden sollen. – abligh

0

Kannst du den lua_State nicht löschen? Entfernen Sie alle Threads und die manuell gesetzten Globals. Möglicherweise müssen Sie die Benutzerumgebung von der globalen Umgebung trennen.

+0

Ist die "Benutzerumgebung" vom lua_State getrennt? – Virus721

+0

Es gibt eine globale Umgebung, die Daten wie 'Tabelle' und 'Drucken' usw. enthält. Je nach Implementierung ist dies auch die Benutzerumgebung. Wenn ein Benutzer '' 'a = 123''' tut, dann gibt es ein Feld _a_ in der globalen Umgebung. Sie können es C-Seite (ich weiß nicht wie) oder Lua Seite, mit einem einfachen getfenv/setfenv (oder _ENV), erstellen eine neue Umgebung mit einem Metafeld __index auf den alten zeigen. – EinsteinK