当类被删除/垃圾回收时调用函数。

我有一个类,在它的构造函数中打开一个 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
点赞
用户2289509
用户2289509

在手册中寻找 finalizer 链接

2013-04-27 21:32:14
用户1442917
用户1442917

您没有提到使用的 Lua 版本,但在 Lua 5.1 中,__gc 在表中无法使用。这样的话,可能会有用(它使用 Lua 5.1 的 newproxy hack):

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 的建议值得检查...

2013-04-27 23:09:33
用户2328533
用户2328533

对于你的特定情况,根据其 源代码,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;
}

但是我认为,在 GC 上释放此类资源应该是备用解决方案:你的对象可能在相当长的时间后才能 GC,因此 SQLite 句柄将在此期间保持打开状态。一些语言提供了机制,尽早释放未管理的资源,例如 Python 的 with 或 C# 的 using

不幸的是,Lua 没有提供这样的特性,因此你应该在可能的情况下自行调用 close,例如在你的类上添加一个 close 方法。

2013-04-28 07:28:12