2016-10-12 53 views
1

我正在將Delphi 5源代碼移植到Delphi 10 Berlin。我的項目中有很多導出函數的DLL。這些函數是從其他DLL中調用的。有兩個DLL我不能遷移到Delphi 10,但我仍然想在我的程序中使用它們。 下面一個例子:在不同的Delphi版本之間發送TStringList

function DoSomething(aList: TStringList): Boolean; external 'Delphi5.dll'; 

我想從我的德爾福10項目稱爲 「DoSomething的」。但問題是,Delphi 5中的TStringList與Delphi 10 Berlin(unicode)中的TStringList不兼容。它會工作,當DoSomething會有一個像「aString:AnsiString」的參數,因爲AnsiString在Delphi 5中與「字符串」兼容。

有沒有一種方法可以在這兩個Delphi版本之間發送列表?也許是TList或其他什麼?當然,我可以發送一個帶有字符串之間的分隔符的AnsiString來模擬一個列表,但我想要一個乾淨的解決方案,因爲我有很多這些導出函數。

謝謝!

+1

該設計是主要缺陷。你永遠不應該永遠不會跨DLL邊界傳遞對象。如果這取決於我,我會完全重新設計這個來傳遞原始數據。也許甚至可以沿着FindFirst/FindNext的方向。 –

+0

如果您的程序曾經工作過,那只是偶然。您需要重新設計界面。 –

+0

更何況,你使用錯誤的調用約定。 –

回答

4

如果它是爲了在DLL內部使用,反之亦然,我們絕不應該將EXE中的對象引用傳遞給DLL。只有當所有的DLL都將對象傳遞迴EXE(反之亦然)時,才能將對象引用安全地傳遞給DLL,例如通過回調函數。

正如您所見,如果EXE和DLL未使用相同版本的Delphi編譯,則對象引用無效。即使它們使用相同的版本進行編譯,我懷疑某些編譯器選項可能會使它們不兼容(想到{$Align},但我從未驗證過它)。即使如此,仍可能會發生一些不兼容問題(例如由於RTTI不匹配導致的"Cannot assign TStringList to TStringList"錯誤)。

某些可以通過對代碼的最小修改來解決問題的方法是更改​​函數的聲明以將接口傳遞給DLL,並創建支持該接口的包裝器TStringList。所述接口將需要支持從TStringList所需的所有功能。

function DoSomething(aList: IStringList): Boolean 

接口可以DLL/EXE之間(只要它們使用相同的接口定義當它們被編譯)被傳遞,而不最相關的對象引用的問題。 (編輯:你仍然需要確保傳遞到接口的方法的數據是安全的傳遞到/從DLL

這就是說,接口應 明確使用AnsiString類型 使用空值終止PAnsiChar,或者甚至是WideString(它可以安全地發送到/從DLL - Reference)。

function DoSomething(aListText: PAnsiChar): Boolean 

function DoSomething(aListText: WideString): Boolean 

不要使用String,這是在Delphi 5 AnsiStringUnicodeString是德爾福10.不要使用AnsiString,因爲它不是德爾福5和Delphi 10之間的兼容由於內部結構的差異。

+3

柏林的'AnsiString'與Delphi 5中的'AnsiString'不兼容,它的內部結構在Delphi 2009中改變了。在DLL中傳遞任何非POD數據類型是不安全的邊界。這包括所有Delphi管理的類型,包括'AnsiString'和'UnicodeString',但不包括'WideString'(由OS管理,因此安全使用)。 –

+0

@RemyLebeau好的......我相應地更新了我的答案。 –

+0

'AnsiString'不一定在使用相同編譯器構建的兩個模塊之間兼容。這也需要共享內存管理器。 –

相關問題