在IIS网络服务器上调用Delphi DLL的ASP.NET Web应用程序,在返回PChar字符串时锁定

时间:2012-02-17 04:32:39

标签: c# delphi iis interop

如果我没有返回任何内容,则工作正常,或者返回一个整数。但是,如果我试图返回一个PChar,即..

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

网络应用程序只是冻结,我看着它的内存数量在任务管理器中逐渐变得越来越高。

奇怪的是,DLL在VStudio调试服务器或C#应用程序上运行良好。我唯一能想到的就是IIS服务器在64位Windows中运行。

它似乎不是兼容性问题,因为我可以成功写入文本文件并从DLL中执行其他操作...我只是不能返回PChar字符串。

尝试使用PWideChar,尝试返回'something \ 0',尝试了我能想到的一切。不幸的是没有运气。

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

string result = SomeFunction();

的Delphi:

library TheLib;

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

exports
    SomeFunction

3 个答案:

答案 0 :(得分:5)

Dampsquid's analysis是正确的,所以我不再重复了。但是,我更喜欢不同的解决方案,我觉得更优雅。我对这类问题的首选解决方案是使用Delphi Widestring BSTR

在Delphi方面,你可以这样写:

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

在C#方面,你这样做:

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

就是这样。因为双方都使用相同的COM分配器进行内存分配,所以这一切都可以正常工作。

更新1

@NoPyGod有趣地指出此代码因运行时错误而失败。看了这个后,我觉得这是Delphi端的一个问题。例如,如果我们按原样保留C#代码并使用以下内容,则会解决错误:

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

似乎Delphi返回的类型WideString的值没有得到应有的处理。 Out参数和var参数按预期处理。我不知道为什么返回值会以这种方式失败。

更新2

事实证明,WideString返回值的Delphi ABI与Microsoft工具不兼容。您不应该使用WideString作为返回类型,而是通过out参数返回它。有关详细信息,请参阅Why can a WideString not be used as a function return value for interop?

答案 1 :(得分:3)

你不能返回这样的字符串,字符串是函数的本地字符串,一旦函数返回就会被释放,而返回的PChar指向无效的位置。

你需要传入一个指针,在DLL中填充,动态创建字符串并将其释放回c#代码中,或者在你的DLL中创建一个静态缓冲区并返回它。

到目前为止,最安全的方法是将指针传递给函数,即

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

在调用dll之前,你应该将MaxLength设置为缓冲区的sixe,以便dll可以检查是否有足够的空间来返回数据。

答案 2 :(得分:-1)

尝试在应用程序池高级设置中启用32位应用程序:

enter image description here