2012-02-17 44 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

相关问题