2011-11-20 65 views
-4

我正在開發此版本的德里2009應用程序,SQLite數據庫版本3.7.9,由Zeos組件訪問。開始關閉 - 如果不存在,我可以創建一個數據庫,創建表並插入記錄 - 「正常的東西」。有一張表包含用於連接某些舊設備的串行參數,並且需要將串行通信處理程序通知連接參數更改,但Zeos組件不支持SQLite上的事件。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/CBtableNamePChars在中國字符的字符串。

我試圖追查回調是從所謂的被人指指點點 - 呼叫鏈通過Zeos驅動程序代碼,出於某種原因。打破了這個過程,我檢查了堆棧指針,在回調之前和之後都是一樣的。

所以,我設置了'空'回調,回調在預期點被調用,但是看起來有些狡猾的參數,回調返回到正確的SP。我似乎已經做了一切正確的,但...:((

有沒有人看到了這一點,(或固定它甚至:)

您能否提供一個機制,使一個aparrently成功的回調可以pesuade的應用程序?後來產生遞歸異常?

沒有人有進一步的調試有什麼建議?

RGDS, 馬丁

+0

您是否嘗試將CBdatabaseName和CBtableName回調函數參數更改爲PAnsiChar? IIRC SQLite希望在這裏使用ansichars。 – Linas

+0

我現在就試試。更新 - 我只是嘗試在調試器外部運行EXE - 它被操作系統用DEP盒子阻止!看起來就像一個退貨地址被損壞,但是在哪裏? –

+0

@Linas - 好的,謝謝,那是中國人走了。現在使用PAnsiChar和調試器爲CBdatabaseName和CBtableName顯示正確的值。 –

回答

1

你必須使用SQLite頭的德爾福的正確翻譯的問題d帶連接:

  1. 不是stdcall,但必須是cdecl
  2. 您的function DBcallback必須是procedure。因爲void(*)(...)是返回void的C函數的指針。
  3. 不是PChar,但必須是PAnsiChar。對於非Unicode的Delphi來說,對於Unicode Delphi來說,它可能並不重要,它只是一個正確的翻譯。
  4. 您正在使用編譯時動態鏈接(external 'sqlite3.dll' ...)到sqlite3.dll。但ZeosLib使用運行時動態鏈接(LoadLibrary & GetProcAddress)。這可能會導致「DLL地獄」的問題,當你的EXE加載一個sqlite3.dll時,ZeosLib打算加載另一個sqlite3.dll。
+0

謝謝!當我移動'sqlite3_update_hook'設置時,我發現了關於cdecl的問題調用它自己的一個小程序,然後調用過程 - 返回值變大了,改成cdecl允許程序運行OK,所以我把回調函數改爲了cdecl,看起來回調函數是否聲明並不重要Delphi函數或proc - 不會改變症狀。 –