2012-02-17 73 views
3

如果我不返回任何東西,或者我返回一個整數,就可以正常工作。但是,如果我嘗試返回PChar類型,即..在web服務器上調用Delphi DLL的ASP.NET web應用程序,在返回PChar字符串時鎖定

result := PChar('') or result:= PChar('Hello') 

的Web應用程序只是凍結了,我看它的內存數逐漸得到任務管理器高。

奇怪的是,該DLL在VStudio調試服務器上或通過C#應用程序正常工作。我能想到的唯一的事情就是,IIS服務器運行在64位Windows上。

它似乎不是一個兼容性問題,雖然因爲我可以成功地寫入文本文件並從DLL做其他事情......我只是不能返回一個PChar字符串。

嘗試使用PWideChar,試圖返回'東西\ 0',嘗試了我能想到的一切。不幸的是不幸運。

[DllImport("TheLib.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)] 
private static extern string SomeFunction(); 

string result = SomeFunction(); 

德爾福:

library TheLib; 

function SomeFunction() : PChar export; stdcall; 
begin 
return PChar(''); 
end; 

exports 
    SomeFunction 

回答

4

Dampsquid's analysis是正確的,所以我不會再重複。不過,我更喜歡另一種我覺得更優雅的解決方案。我最喜歡的解決方案是使用Delphi Widestring這是一個BSTR

在德爾福方面你寫這樣的:

function SomeFunction: Widestring; stdcall; 
begin 
    Result := 'Hello'; 
end; 

而且你做這樣的C#的一面:

[DllImport(@"TheLib.dll")] 
[return: MarshalAs(UnmanagedType.BStr)] 
private static extern string SomeFunction(); 

就是這樣。因爲雙方都使用相同的COM分配器來分配內存,所以這一切都正常。


@NoPyGod有意思地指出,這段代碼因爲運行時錯誤而失敗。考慮到這一點,我覺得這是德爾福的一個問題。例如,如果我們離開的C#代碼,因爲它是和使用以下,則錯誤得到解決:

function SomeFunction: PChar; stdcall; 
begin 
    Result := SysAllocString(WideString('Hello')); 
end; 

這似乎是WideString類型的德爾福返回值是沒有處理,因爲他們應該的。 Out參數和var參數按照預期進行處理。我不知道爲什麼返回值以這種方式失敗。

+0

我必須等到星期一在工作上試用IIS的解決方案,但背後的理由聽起來很可靠。但有一件事..我一直在家裏測試代碼,我無法獲得返回值的工作,它只是給出了一個異常'嘗試讀取或寫入受保護的內存。'。然而,我可以通過使用'out'變量並以這種方式傳遞結果來實現我想要做的事情。你知道我爲什麼不能返回嗎?我正在編碼結果,就像在你的代碼中一樣。是因爲它是德爾福2007?我可以使用'out'技巧,但我想知道爲什麼它是必要的。 – NoPyGod 2012-02-18 22:40:26

+0

我看到Alex在這裏有同樣的問題 - http://stackoverflow.com/questions/8533505/accessing-delphi-dll-throwing-ocasional-exception – NoPyGod 2012-02-18 22:42:32

+0

這裏是我的來源http://pastebin.com/NfWLdF6V – NoPyGod 2012-02-18 22:46:41

-1

嘗試啓用應用程序池的32位應用程序的高級設置:

enter image description here

+0

-1這與我判斷的問題無關。 – 2012-02-17 12:34:52

+0

我相信這是真的使用32位** COM ** DLL時。而不是在C#中導入時。 – kobik 2012-02-17 14:34:38

+0

我的歉意O :-) – 2012-02-17 14:47:06

3

您不能返回這樣的一個字符串,字符串是本地到函數,並且只要函數返回,就會被釋放,使得返回的PChar指向一個無效的位置。

你需要傳遞一個指針來填充DLL中的動態創建字符串並將其釋放回c#代碼或在你的DLL中創建一個靜態緩衝區並返回它。

迄今爲止最安全的方法是將一個指針傳遞給函數即

function SomeFunction(Buffer: PChar; MaxLength: PInteger): wordbool; stdcall; 
{ 
    // fill in the buffer and set MaxLength to length of data 
} 

你應該設置的MaxLength到緩衝區的sixe調用您的DLL之前,這樣的DLL可以檢查有沒有足夠的空間要返回的數據。

+0

代碼在c#端看起來像什麼?因爲在這裏除了最大長度參數外它看起來一樣。爲什麼doee代碼在iis之外工作?謝謝 – NoPyGod 2012-02-17 12:04:54

+0

我想你犯了一個錯字,如果Pchar是一些變量名。當我到達電腦時,期待着嘗試這個。 – NoPyGod 2012-02-17 12:07:29

+0

你可以返回一個BSTR並讓編組處理。這將是我的首選。 – 2012-02-17 12:18:27

相關問題