2013-03-15 32 views
2

我有此函數簽名一個DLL:錯誤調用的DLL使用Unicode的Delphi

function KP_RecuperarDadosFabricante(EnderecoIp, ChaveAcesso, 
    Porta: string; Return: PAnsiChar): Integer; stdcall; external 'Key.dll'; 

這是從DLL的手動樣品VB.NET代碼:

Dim ret As Integer 
Dim ptrStr As IntPtr 
Dim DadosFab As String 

ptrStr = System.Runtime.InteropServices.Marshal.AllocHGlobal(256) 
ret = KP_RecuperarDadosFabricante("192.168.1.201", "0", "4370", ptrStr) 
DadosFab = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ptrStr) 
System.Runtime.InteropServices.Marshal.FreeHGlobal(ptrStr) 

這是我的Delphi代碼:

procedure TForm1.BitBtn1Click(Sender: TObject); 
var 
    Return: string; 
    pReturn: PAnsiChar; 
begin 
    GetMem(pReturn, 512); 
    FillChar(pReturn^, 512, 0); 
    Memo1.Text:=''; 
    if KP_RecuperarDadosFabricante("192.168.1.201", "0", "4370", pReturn) = 1 then 
    begin 
    Return := StrPas(pReturn); 
    ShowMessage(Return); 
    end 
    else 
    begin 
    ShowMessage('Error'); 
    end; 
end; 

此代碼wor ks在德爾福7,,但不適用於德爾福XE。它總是返回「錯誤」。 如何使此代碼在Delphi XE

+0

**遠**指令已棄用,因爲... mmmm,也許因爲德爾福3如果不是德爾福1,你爲什麼使用它?釋放你獲得的記憶怎麼樣? vb示例釋放它,但是您的代碼每次調用泄漏512個字節! – jachguate 2013-03-15 23:27:57

+0

@jachguate我刪除了「遠」的代碼,但沒有解決問題。內存還沒有問題。謝謝 – dataol 2013-03-15 23:54:15

+0

我沒有說它解決了你的問題,但他們是其他_problems_你。 – jachguate 2013-03-16 04:34:20

回答

7

如果DLL是用Delphi 7編寫的,那麼你不能使用Delphi XE中的那個DLL。即使您將string參數更改爲AnsiString以使字符大小相同,仍然堅持這樣一個事實,即字符串的內部結構在這些版本之間有所變化,因此您從Delphi XE代碼發送的AnsiString不會看起來Delphi 7代碼期望AnsiString的樣子。

如果您有權更改和重新編譯該DLL,則應該將參數設置爲PAnsiChar,而不是像幾乎任何其他Windows上的DLL一樣。還請記住將最終的PChar參數更改爲PAnsiChar


如果DLL是用某種非Delphi語言編寫的,那麼您可以通過更改函數簽名來修復它。非Delphi語言沒有Delphi的string類型,所以聲明一直是錯誤的;從Delphi 7開始工作時,你真是太幸運了。將所有參數更改爲PAnsiChar(包括最終參數);那麼他們將匹配他們可能從原始C代碼中獲得的char*類型。

+4

+1。除非是非常基本的非Delphi特定類型,例如8,16,32和64位整數,32位和64位浮點類型,包含這些類型和指針的記錄,否則絕對不要暴露任何DLL。 – 2013-03-15 21:13:22

+0

謝謝羅布。我將簽名從Pchar更改爲PAnsiChar,但我沒有解決問題。這是VB.NET手冊中dll的示例代碼:>>> Dim ret As Integer Dim ptrStr As IntPtr Dim DadosFab As String ptrStr = System.Runtime.InteropServices.Marshal.AllocHGlobal(256) RET = KP1510_RecuperarDadosFabricante( 「192.168.1.201」, 「0」, 「4370」, ptrStr) DadosFab = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ptrStr) 系統。Runtime.InteropServices.Marshal.FreeHGlobal(ptrStr) – dataol 2013-03-15 22:13:23

+0

我不知道是否使用Delphi 7編寫DLL – dataol 2013-03-15 22:20:15