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

如果我不返回任何内容,则工作正常,或者返回一个整数。 但如果我试图返回一个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 

Dampsquid的分析是正确的,所以我不再重复。 但是,我更喜欢不同的解决方案,我觉得它更优雅。 我对这种问题的首选解决方案是使用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

事实certificate,用于WideString返回值的Delphi ABI与Microsoft工具不兼容。 您不应该使用WideString作为返回类型,而是通过out参数返回它。 有关更多详细信息,请参阅为什么不能将WideString用作互操作的函数返回值?

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

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

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

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

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

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

在此处输入图像描述