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