2009-05-07 3 views
1

OK, also habe ich eine C++ - Klasse, die Lua mit SWIG ausgesetzt ist. Das Skript erstellt das Objekt, aber eine Verwaltungsklasse weist auch einen Zeiger auf das Objekt auf, so dass es aus irgendeinem Grund in C++ (oder einem anderen Skript) geändert werden kann.Steuerung des Lua5.1-Garbage Collectors

Das Problem ist, dass, wenn das Skript beendet das Objekt frei ist, wie kann ich kontrollieren, was der Müllsammler sammelt, ohne ein GC-Metamethode zu implementieren? Hier

ein Beispiel:

--Script that creates the object 
someObject = Utils.Object("Obj name"); 

nun das Objekt selbst mit dem Manager registriert hat, damit der Rest der Anwendung (und anderen Skripte) darauf zugreifen kann.

Klar kein sehr realistisches Beispiel, aber hoffentlich illustriert es meine Frage. Gibt es eine Möglichkeit, den Garbage Collector ohne eine GC Metamethode in C++ zu veto?

Nur um zu verdeutlichen, der Manager ist in C++, und Utils ist der Modulname Gehäuse der exponierten Klasse. Auch das Objekt registriert sich in seinem Konstruktor beim Manager.

Vielen Dank im Voraus.

+0

Es würde helfen, wenn Sie jedes Codefragment beschriften, ob das Codefragment C++ oder Lua ist. –

+0

Rechts habe ich sie mit lua Kommentare beschriftet. –

Antwort

2

Lua's GC kennt nur Referenzen innerhalb von Lua, was eine vernünftige Implementierungsbeschränkung darstellt. Dies bedeutet, dass die Lebensdauer eines Objekts von Lua kontrolliert wird. Wenn ein Objekt, das durch Ausführen eines Skripts oder einer Funktion erstellt wurde, für spätere Skripts oder Funktionen verfügbar sein muss, muss ein Verweis darauf im Lua-Status beibehalten werden, damit der GC den Namen noch verwendet. Ansonsten ist es nicht von Müll zu unterscheiden und kann jederzeit verworfen werden.

Dies ist einer der Zwecke der Lua-Registrierungstabelle. Die C-Seite kann leicht einen Verweis auf ein beliebiges Lua-Objekt halten, indem sie es in die Registrierungstabelle platziert. Der Schlüssel kann entweder ein eindeutiger Wert sein, der der C-Bibliothek bekannt ist (die Adresse einer static-Variablen, die in helle Benutzerdaten konvertiert wird, ist oft eine gute Wahl, da sie nicht mit irgendeinem Schlüssel aus einer anderen Bibliothek kollidieren kann). Alternativ stellt der Funktionsaufruf luaL_ref(L, LUA_REGISTRYINDEX) das Element an den Anfang des Stapels in der Registrierungstabelle und gibt einen eindeutigen Ganzzahlschlüssel zurück. Dies funktioniert gut zum Speichern einer vom Skript bereitgestellten Rückruffunktion auf eine Weise, die sowohl die Funktion vor dem GC schützt, als auch einen "Zeiger" (den Ganzzahlschlüssel) in einer C-Struktur speichert, so dass sie abgerufen und aufgerufen werden kann später.

Beachten Sie, dass luaL_ref() verwendet werden kann, um Verweise in einer beliebigen Tabelle zu verwalten. Daher kann es sehr sinnvoll sein, eine private Tabelle für dieses Modul anstelle der globalen Registrierungstabelle zu verwenden. In diesem Fall könnte die Tabelle ObjManager selbst ein guter Kandidat sein.

0

Ja; Habe Utils.Object stopft das Objekt in eine private Tabelle. Dann wird es nie gesammelt werden, aber Sie können Spiele spielen (Code nicht getestet):

do 
    local retained = { } -- table forces objects to be retained 
    local old_util_object = Util.Object 
    Util.Object = function(...) 
    local obj = old_util_object(...) 
    retained[obj] = true 
    return obj 
    end 
    Util.Free = function(obj) 
    assert(retained[obj]) 
    retained[obj] = nil -- now obj can be garbage-collected 
    end 
end 

Wenn Sie das gleiche Problem auf der C++ Seite lösen wollen, müssen Sie Ihre C++ Code zuteilen einen privaten Tisch und setzen es in der Lua-Registrierung. Dann können Sie das gleiche Insertion/Deletion-Spiel spielen, nur mit der C-API anstelle von Lua-Quelle. Angenommen, Sie kennen sich mit der C-API von Lua aus, ist das ganz einfach. Wenn Sie die C API noch nicht verwendet haben, wird es nie einen besseren Zeitpunkt geben, um mit dem Lernen zu beginnen.

+0

Danke für die Antwort, aber es hilft nicht wirklich. Ich suchte nach einer Möglichkeit, es in C/++ zu machen. Ich habe meine Frage geklärt, um das zu zeigen. –

Verwandte Themen