我正在使用Zeite组件访问的SQLite数据库版本3.7.9开发这个德里2009应用程序。开始关闭 - 如果不存在,我可以创建一个数据库,创建表并插入记录 - “正常的东西”。有一个小表包含用于连接到某些旧设备的串行参数,并且需要通知串行通信处理程序连接参数更改,但Zeos组件不支持SQLite上的事件。
我查看了SQLite API并且有一个“数据更改通知回调”,所以我着手实现这一点。设置原型是:
void *sqlite3_update_hook(
sqlite3*,
void(*)(void *,int ,char const *,char const *,sqlite3_int64),
void*
);
所以,在Delphi中,我导入了DLL调用:
function sqlite3_update_hook(pDB:pointer;pCallback:pointer;aux:pointer): pointer; stdcall;
..
function sqlite3_update_hook; external 'sqlite3.dll' name 'sqlite3_update_hook';
..并宣布一个空的回调用于测试:
function DBcallback(aux:pointer;CBtype:integer;CBdatabaseName:PChar;CBtableName:PChar;CBrowID:Int64):pointer; stdcall;
begin
end;
..并调用设置:
sqlite3_update_hook(SQLiteHandle,@DBcallback,dmOilmon);
SQLiteHandle
是连接后从驱动程序检索的数据库的sqlite3*
指针。 dmOilmon
是DataModule实例,因此,当正常工作时,我可以从回调中调用一些方法,(是的,我知道回调是在一个未知的线程中 - 我可以处理那个好,我只是发信号信号灯)。
好消息:当我运行应用程序时,DBcallback
在第一次插入时被成功调用。坏消息:一段时间后,该应用程序爆炸了“太多异常”,通常是一个充满'??'的CPU窗口,(偶尔的替代方案是系统死机和重启 - Vista Ultimate 64)。在回调中断,aux,CBtype
和CBrowID
都是预期的,但调试器工具提示显示CBdatabaseName
/ CBtableName
PChars
指向一个字符串汉字..
我试图追踪调用回调的位置 - 由于某种原因,调用链在Zeos驱动程序代码中传递。在那里打破并单步执行,我检查了堆栈指针,它在回调之前和之后都是一样的。
所以,我设置了'空'回调,回调在预期的点被调用但是看起来很狡猾的参数,回调返回到它与SP正确相关的位置。我好像做得对,但...... :((
有没有人见过这个,(或者甚至修好了它?)?
你能建议一种机制,通过这种机制,一个成功的回调可以使应用程序稍后产生递归异常吗?
有没有人有进一步调试的建议?
RGDS, 马丁
答案 0 :(得分:2)
您在将SQLite标头正确转换为Delphi并使用链接时遇到了问题:
stdcall
,但必须是cdecl
。function DBcallback
必须是procedure
。因为void(*)(...)
是指向返回void
的C函数的指针。PChar
,但必须是PAnsiChar
。对于非Unicode Delphi,它可能并不重要,对于Unicode Delphi来说,它只是一个正确的翻译。external 'sqlite3.dll' ...
)到sqlite3.dll。但ZeosLib使用运行时动态链接(LoadLibrary
& GetProcAddress
)。这可能导致“DLL地狱”问题,当你的EXE加载一个sqlite3.dll,ZeosLib计划加载另一个sqlite3.dll。