首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >将字符串从delphi dll返回到64位的C#调用者?

将字符串从delphi dll返回到64位的C#调用者?
EN

Stack Overflow用户
提问于 2018-08-22 04:25:55
回答 1查看 0关注 0票数 0

我有一个C#应用程序,它使用以下代码调用本机Delphi dll:

C#

代码语言:javascript
复制
[DllImport("NativeDLL.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern int GetString(string out str);

Delphi

代码语言:javascript
复制
function GetString(out a: PChar): Integer; stdcall;
begin
  a := PChar('abc');
  Result := 1;
end;

这在32位应用程序中工作正常。但是当我为64位编译C#exe和Delphi dll时,我遇到了一个奇怪的问题。在Delphi调试器中调用GetString之后,我可以看到.NET代码中某处出现异常,并且Debugger Output窗口中出现以下字符串:“检测到严重错误c0000374”。Google表示此错误与堆损坏有关。我尝试使用ref / var参数修饰符而不是out / out。仍然没有运气。为什么我会收到此错误?我应该为64位使用不同的调用约定吗?

C#

代码语言:javascript
复制
[DllImport("NativeDLL.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
public static extern string GetString(string a);

Delphi

代码语言:javascript
复制
function GetString(a: PChar): PChar; stdcall;
var
  inp: string;
begin
  inp := a;
  Result := PChar('test ' + inp);
end;

工作正常。但我确实需要返回一个字符串作为out参数。

EN

回答 1

Stack Overflow用户

发布于 2018-08-22 14:03:48

你需要:

  1. 从共享堆分配,以便托管代码可以从该堆释放。p / invoke的共享堆是COM堆。
  2. 在托管端分配内存,并将内容复制到本机端的缓冲区中。

选项2总是更可取的。它看起来像这样:

代码语言:javascript
复制
[DllImport("NativeDLL.dll", CharSet = CharSet.Unicode)]
public static extern int GetString(StringBuilder str, int len);

在原生方面,你会有

代码语言:javascript
复制
function GetString(str: PChar; len: Integer): Integer; stdcall;
begin
  StrLCopy(str, 'abc', len);
  Result := 1; // real code would have real error handling
end;

然后这样调用:

代码语言:javascript
复制
StringBuilder str = new StringBuilder(256);
int retval = GetString(str, str.Capacity);

如果你想尝试选项1,它在管理方面看起来像这样:

代码语言:javascript
复制
[DllImport("NativeDLL.dll", CharSet = CharSet.Unicode)]
public static extern int GetString(out string str);

和这个本地人一样:

代码语言:javascript
复制
function GetString(out str: PChar): Integer; stdcall;
begin
  str = CoTaskMemAlloc(SizeOf(Char)*(Length('abc')+1));
  StrCopy(str, 'abc');
  Result := 1; // real code would have real error handling
end;

当托管代码将内容复制str到字符串值时,它会调用CoTaskMemFree 返回的指针。

这很容易:

代码语言:javascript
复制
string str;
int retval = GetString(out str);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/-100006035

复制
相关文章

相似问题

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