Временное решение Lua 5.1 для метаметода __gc для таблиц
В настоящее время я сталкиваюсь с проблемой, что вы не можете использовать __gc
метод для таблиц в Lua 5.1, так как они реализованы в Lua 5.2. Тем не менее, я хочу освободить выделенные собственные ресурсы, как только таблица lua будет собрана. Можно ли сделать обходной путь, который дает мне функциональность __gc
метаметод в Lua 5.2 для Lua 5.1?
1 ответ
В lua 5.1 единственные значения lua, которые работают с __gc
метаметод userdata
, Естественно, любой взлом или обходной путь должен будет включать userdata
каким-то образом. Обычно нет способа просто создать newuserdata со стороны lua, но есть одна "скрытая" недокументированная функция newproxy
для этого просто.
newproxy
принимает необязательный параметр bool или userdata. Если вы проходите в true
тогда вы получите пользовательские данные с новым прикрепленным метатабилем. Если вы переходите в другой userdata
тогда новым userdata будет назначена та же метатабельная, что и переданной.
Так что теперь вы можете просто взломать функцию, которая сделает __gc
работа на столах:
function setmt__gc(t, mt)
local prox = newproxy(true)
getmetatable(prox).__gc = function() mt.__gc(t) end
t[prox] = true
return setmetatable(t, mt)
end
И быстрый тест, чтобы подтвердить поведение:
iscollected = false
function gctest(self)
iscollected = true
print("cleaning up:", self)
end
test = setmt__gc({}, {__gc = gctest})
collectgarbage()
assert(not iscollected)
test = nil
collectgarbage()
assert(iscollected)
Обратите внимание, что Lua 5.2+ и более поздних версий больше не имеют newproxy
поскольку __gc
официально поддерживается на столах.