0

我有一个在其构造函数中打开 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
4

3 回答 3

2

您没有提及您使用的 Lua 版本,但__gc不适用于 Lua 5.1 中的表。像这样的东西可能会起作用(它对newproxyLua 5.1 使用 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-27T23:09:33.100 回答
2

对于您的特定情况,根据其源代码,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 句柄将在此期间保持打开状态。一些语言提供了尽早释放非托管资源的机制,例如 Pythonwith或 C# using

不幸的是 Lua 没有提供这样的特性,所以你应该close尽可能地调用自己,close例如在你的类上创建一个方法。

于 2013-04-28T07:28:12.777 回答
1

finalizer 在手册中查找。

于 2013-04-27T21:32:14.583 回答