2009-05-07 5 views
1

OK, donc j'ai une classe C++ qui est exposée à Lua en utilisant SWIG. Le script crée l'objet mais une classe de gestionnaire a également un pointeur vers l'objet afin qu'il puisse être modifié en C++ (ou un autre script) pour une raison quelconque. Le problème est que lorsque le script se termine l'objet est libéré, comment puis-je contrôler ce que le Garbage collector recueille sans avoir à implémenter une métaméthode gc?Contrôle du garbage collector de Lua5.1

Voici un exemple:

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

maintenant l'objet lui-même est enregistré avec le gestionnaire de sorte que le reste de l'application (et d'autres scripts) peuvent y accéder. Clairement pas un exemple très réaliste mais j'espère que cela illustre ma question. Y a-t-il un moyen d'opposer son veto au garbage collector sans une métaméthode gc en C++? Pour clarifier le gestionnaire est en C++, et Utils est le nom du module qui héberge la classe exposée. De plus, l'objet s'enregistre lui-même auprès du gestionnaire dans son constructeur.

Merci d'avance.

+0

Il serait utile si vous étiquetez chaque fragment de code pour savoir si le fragment de code est C++ ou Lua. –

+0

A droite je les ai étiquetés avec des commentaires lua. –

Répondre

2

Le GC de Lua ne connaît que les références contenues dans Lua, ce qui constitue une contrainte d'implémentation raisonnable. Cela implique que la vie d'un objet est sous le contrôle de Lua. Si un objet créé en exécutant un script ou une fonction doit être disponible pour des scripts ou des fonctions ultérieurs, une référence à celui-ci doit être conservée dans l'état Lua afin que le GC sache il est toujours utilisé. Sinon, il est indiscernable des déchets et peut être jeté à tout moment.

Ceci est l'un des buts de la table de registre Lua. Le côté C peut facilement contenir une référence à n'importe quel objet Lua en le plaçant dans la table de registre. La clé peut être soit une valeur unique connue de la bibliothèque C (l'adresse d'une variable static convertie en données utilisateur légères est souvent un bon choix car elle ne peut pas entrer en collision avec une clé d'une autre bibliothèque). Sinon, l'appel de la fonction luaL_ref(L, LUA_REGISTRYINDEX) placera l'élément en haut de la pile dans la table de registre et renverra une clé entière unique. Cela fonctionne bien pour stocker une fonction de rappel fournie par un script d'une manière qui protège à la fois la fonction du GC et lui permet de stocker un "pointeur" (la clé entière) dans une structure C afin qu'il puisse être récupéré et appelé plus tard. Notez que luaL_ref() peut être utilisé pour gérer des références dans n'importe quelle table, il peut donc être judicieux d'utiliser une table privée pour votre module plutôt que la table de registre globale. Dans ce cas, le tableau ObjManager lui-même pourrait être un bon candidat.

0

Oui; avez Utils.Object bourrer l'objet dans une table privée. Ensuite, il jamais être collectées, mais vous pouvez jouer à des jeux (code non testé):

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 

Si vous voulez résoudre le même problème sur le côté C, ont votre code C++ allouent une table privée et mettre dans le registre Lua. Ensuite, vous pouvez jouer au même jeu d'insertion/suppression, en utilisant uniquement l'API C au lieu de la source Lua. En supposant que vous connaissiez l'API C de Lua, c'est simple. Si vous n'avez jamais utilisé l'API C auparavant, il n'y aura jamais de meilleur moment pour commencer à apprendre.

+0

Merci pour la réponse, mais cela n'aide pas vraiment. Je cherchais un moyen de le faire en C/++. J'ai clarifié ma question pour le montrer. –

Questions connexes