首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >ASP.NET web应用程序调用IIS服务器上的Delphi DLL,返回PChar字符串时锁定

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

Stack Overflow用户
提问于 2012-02-17 12:32:39
回答 3查看 2.2K关注 0票数 4

如果我不返回任何东西,或者我返回一个整数,就可以正常工作。但是如果我尝试返回一个PChar,即..

代码语言:javascript
复制
result := PChar('')  or   result:= PChar('Hello')

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

奇怪的是,DLL在VStudio调试服务器上或通过C#应用程序工作得很好。我能想到的唯一有区别的是IIS服务器是在64位Windows上运行的。

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

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

代码语言:javascript
复制
[DllImport("TheLib.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
private static extern string SomeFunction();

string result = SomeFunction();

delphi:

代码语言:javascript
复制
library TheLib;

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

exports
    SomeFunction
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-02-17 20:34:22

Dampsquid's analysis是正确的,所以我不再重复了。然而,我更喜欢一种不同的解决方案,我觉得这样会更优雅。对于这样的问题,我首选的解决方案是使用Delphi Widestring,它是一个BSTR

在Delphi端,你可以这样写它:

代码语言:javascript
复制
function SomeFunction: Widestring; stdcall;
begin
  Result := 'Hello';
end;

在C#端,你可以这样做:

代码语言:javascript
复制
[DllImport(@"TheLib.dll")]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern string SomeFunction();

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

更新1

@NoPy神有趣地指出,这段代码会因为运行时错误而失败。在研究过这个问题之后,我觉得这是Delphi端的一个问题。例如,如果我们保持C#代码不变,并使用以下代码,那么错误就会得到解决:

代码语言:javascript
复制
function SomeFunction: PChar; stdcall;
begin
  Result := SysAllocString(WideString('Hello'));
end;

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

更新2

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

票数 5
EN

Stack Overflow用户

发布于 2012-02-17 17:51:58

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

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

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

代码语言:javascript
复制
function SomeFunction( Buffer: PChar; MaxLength: PInteger ): wordbool; stdcall;
{
  // fill in the buffer and set MaxLength to length of data
}

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

票数 3
EN

Stack Overflow用户

发布于 2012-02-17 17:06:48

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

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9322938

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档