在用Delphi30開發軟件時,出現了硬件驅動程序 (DLL)中的函數和過程不能正常調用的問題,該硬件由英國Schlumberger公司生產,驅動程序用匯編語言編寫的。其《編程指南》給出的 Microsoft C的示范程序均能正常運行。但運行此軟件時現出的錯誤提示為: Access violation at address ×××××××× in module…… 經仔細分析,才發現問題出現在函數調用模式上。
Delphi30支持五種調用模式:register、cdec l、pascal、stdcall和safecall。根據調用模式的不同,參數可以通過CPU的寄存器或堆棧傳遞給函數和過程。reg ister模式使用CPU的三個寄存器傳遞參數,而其它模式則用堆棧來傳遞參數。在register和pascal模式下從左至右傳遞參數,即參數表中最左邊的參數最先被求值並傳遞,而最右邊的參數最後求值並傳遞。另三種模式cdecl、std call和safecall則從右至左傳遞參數。這些模式中除了cd ecl外,都是由過程和函數在返回時清除堆棧中的參數,而對於 cdecl模式,需由調用者在調用結束時清除堆棧中的參數。
如何選擇調用模式,有以下三條規則:
1Delphi30使用register模式作為缺省調用模式以提高運行效率。
2如果有調用關系的幾個模塊是用不同語言編寫的,其接口應使用 stdcall模式。
3如果要實現雙界面函數和過程,應使用safec all模式。
所以解決我們的問題只要選用stdcall模式即可, Schlumberger公司的《編程指南》上在Microsoft C環境下的 DLL函數說明(僅舉兩例)為:
void(FAR PASCAL *Imp_ Connect)(unsigned s hort far*,short far*);
void(FAR PASCAL *Imp_ Init)(short far*,short far*);
相應的在Delphi30下DLL函數引入說明為:
procedure Imp_ Connect(var CardAddress:wor d;var CardHandle:smallint);stdcall;
procedure Imp_ Init(var Poll_Tab:smallint;var ErrorFlag:smallint;var CardHandle:smallint);stdcall;
這樣修改以後,程序即可正常運行(原來我們沒有說明調用模式,即使用缺省的 register模式),由此我們也可得出一個經驗:對一些高版本的新軟件,使用時要注意改進和擴充,並經常看看幫助文件,定會大有裨益。