Delphi寫DLL要注意的問題 (轉)


今天寫一個dll准備給.net調用, dll寫出之后給用delphi測試一下, 居然出錯, 更別說給.net調用了.查來查去原來是參數和返回值使用string類型, 后面看了'Delphi 編寫 DLL 返回字符串,.net 調用。' 這篇文章才解決, 順便也收藏了一下,原來delphi寫的dll有這么多限制的.

 

這一點我們需要注意  
a. 參數和返回值為string、動態數組類型時,DLL和EXE都要把ShareMem作為.dpr工程的第一個單元引用。當然最好是不要使用 string、動態數組類型,可以改用PChar、數組指針類型,如果是混合語言編程使用的話,就一定不能用string、動態數組類型。這樣做的原因是 DLL和EXE的內存管理器(MemoryManager)不是一個,而string、動態數組類型是通過引用計數由Delphi自動進行內存管理的,它 何時分配何時釋放,我們不能顯式的知道的,DLL分配而EXE釋放的話,這樣就出問題了。用ShareMem就是為了讓它們統一使用一個內存管理器進行內 存分配釋放。 關於DLL和EXE內存管理器不同這一點,非常重要! 
b.DLL和EXE的VCL類體系不是一個,它們各自有一套,因此,從EXE傳遞過去的對象,要在DLL中用is判斷類型和as作類型轉換,那都不能得到期望的結果。 如果是bpl,就不會有這個問題  
c.DLL中應用ADO、窗體(模態、非模態、MDI子窗體)、線程等的一些相關問題與今天的主題關系不大,就不作多講了。參考DLL的詳細論述請參考《Windows核心編程》第19、20章。

========================================================

對使用Delphi制作DLL復用文件的建議

在公司里有一些需要制作DLL的場合,因為熟悉、方便和簡易,大多數使用Delphi來制作。現在就這個主題提出一些個人建議。

盡 量使用標准DLL接口。指的是傳遞的參數類型及函數返回類型不能是Delphi特有的,比如string(AnsiString),以及動態數組和含有這 些類型成員的復合類型(如記錄),也不能是包含有這些類型成員數據成員的對象類型,以避免可能的錯誤。如果使用了string類型或動態數組類型,且調用 方不是Delphi程序,則基本上會報錯。如果調用方是Delphi但調用方或被調用方沒有在工程文件的第一包含單元不是ShareMem,也可能會出 錯。

如果調用方是Delphi應用程序,則可能可以使用不包含禁止類型(string, 動態數組)數據成員的對象作為參數或返回值,但也應盡量避免。

如果調用方與被調用方都是Delphi程序,而且要使用string或動態數組作參數,則雙方工程文件的第一包含單元必須是ShareMem。(C++Builder程序的情況可能與此相同,不過沒有測試過。)

如果調用方不是Delphi程序,則string、動態數組、包含string或動態數組的復合數據類型及類實例,都不能作為參數及返回值。

因此,為了提高DLL的復用范圍,避免可能存在的錯誤,應當使用標准WIN32 API標准參數類型,以前使用string的變量,可以使用PChar(s)轉換。動態數組則轉換為指針類型(@array[0]),並加上數組的長度。

如果因為調用方與被調用方都是Delphi程序,為了編寫方便,不想進行上述轉換,則推薦使用運行時包的形式。運行時包可以保證動態分配數據的正確釋放。這樣因為其擴展名(.bpl),顯出該文件僅限於Delphi/C++Builder使用(不象DLL)。

其 次,盡量避免使用overload的函數/過程作輸出,如果同一操作有多個方式,則可以讓函數/過程名有少許差別,類似於Delphi中的 FormatXXXX、CreateXXXX等函數及方法,如CreateByDefaultFile, CreateDefault。

最 后,作為DLL的提供者,應當提供直接編程的接口文件,如Delphi中的.pas或.dcu(最好是.pas,因為可以有注釋)、C及C++中的.h 和.lib。而不是讓使用者們自己創建。如果非要有overload的函數/過程,這一點顯得特別重要。另外,作為Delphi應用,提供的.pas文件 可以是提前連接的(使用external指定DLL中的輸出函數),也可以是后期連接的(使用LoadLibrary、 GetProcAddress),DLL提供者提供編程接口文件,既顯得正式(或HiQoS),又有保障。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM