删除类/垃圾收集时调用函数

时间:2013-04-27 21:28:08

标签: function class lua destroy

我有一个在其构造函数中打开sqlite数据库的类。有没有办法让它在销毁时关闭数据库(无论是由于程序员破坏它还是通过Lua的垃圾收集销毁)?

到目前为止的代码:

local MyClass   = {}
local myClass_mt= {__index=MyClass,  __gc=__del}

function DBHandler.__init()
    -- constructor  
    local newMyClass = {
        db    = sqlite3.open(dbPath)
    }
    return setmetatable(newMyClass , myClass_mt)
end

local function __del()
    self.db.close()
end

3 个答案:

答案 0 :(得分:2)

您没有提到您使用的Lua版本,但__gc不适用于Lua 5.1中的表。这样的事情可能有用(它使用newproxy hack for Lua 5.1):

m = newMyClass
if _VERSION >= "Lua 5.2" then
  setmetatable(m, {__gc = m.__del})
else
  -- keep sentinel alive until 'm' is garbage collected
  m.sentinel = newproxy(true)
  getmetatable(m.sentinel).__gc = m.__del -- careful with `self` in this case
end

对于Lua 5.2,这与您拥有的代码没有什么不同;你没有说出究竟什么不起作用,但是Egor对self.db:close的建议值得检查......

答案 1 :(得分:2)

对于您的特定情况,根据其source code,LuaSQLite在销毁时已经关闭了它的句柄:

/* close method */
static int db_close(lua_State *L) {
    sdb *db = lsqlite_checkdb(L, 1);
    lua_pushnumber(L, cleanupdb(L, db));
    return 1;
}

/* __gc method */
static int db_gc(lua_State *L) {
    sdb *db = lsqlite_getdb(L, 1);
    if (db->db != NULL)  /* ignore closed databases */
        cleanupdb(L, db);
    return 0;
}

但IMO在GC上释放这些资源应该是一个备份解决方案:你的对象可能会在很长一段时间后被GC,因此SQLite句柄将在此期间保持打开状态。有些语言提供了尽早释放非托管资源的机制,例如Python的with或C#using

不幸的是,Lua没有提供此类功能,因此您应尽可能自己致电close,例如在您的课程中使用close方法。

答案 2 :(得分:1)

寻找finalizer in the manual