Lua 5.1 workaround for __gc metamethod for tables

♀尐吖头ヾ 提交于 2019-12-06 00:26:59

In lua 5.1 the only lua values that work with __gc metamethod is userdata. Naturally any hack or workaround will have to involve userdata in someway. Normally there is no way to just create newuserdata from the lua side but there is one "hidden" undocumented function newproxy for doing just that.

newproxy takes an optional bool or userdata parameter. If you pass in true then you get a userdata with a new metatable attached. If you pass in another userdata then the new userdata will be assigned the same metatable as the one passed in.

So now you can just hack together a function that'll make __gc work on tables:

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

And a quick test to confirm the behavior:

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)

IDEOne Demo

Note that lua 5.2+ and later no longer have newproxy since __gc is officially supported on tables.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!