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

前端之家收集整理的这篇文章主要介绍了将字符串从delphi dll返回到64位的C#调用者前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个C#应用程序,它使用以下代码调用本机Delphi dll:

C#@H_403_3@

  1. [DllImport("NativeDLL.dll",CharSet = CharSet.Unicode,CallingConvention = CallingConvention.StdCall)]
  2. public static extern int GetString(string out str);

德尔福@H_403_3@

  1. function GetString(out a: PChar): Integer; stdcall;
  2. begin
  3. a := PChar('abc');
  4. Result := 1;
  5. end;

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

BTW.以下组合工作正常:@H_403_3@

C#@H_403_3@

  1. [DllImport("NativeDLL.dll",CallingConvention = CallingConvention.StdCall)]
  2. public static extern string GetString(string a);

德尔福@H_403_3@

  1. function GetString(a: PChar): PChar; stdcall;
  2. var
  3. inp: string;
  4. begin
  5. inp := a;
  6. Result := PChar('test ' + inp);
  7. end;

工作良好.但我确实需要返回一个字符串作为out参数.@H_403_3@

解决方法

您不能以这种方式从本机托管传递字符串.你的代码在32位也是错误的,你恰好侥幸逃脱它.代码的第二个版本也是错误的.它似乎只能工作.

你需要:@H_403_3@

>从共享堆分配,以便托管代码可以从该堆中解除分配. p / invoke的共享堆是COM堆.
>在托管端分配内存,并将内容复制到本机端的缓冲区中.@H_403_3@

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

  1. [DllImport("NativeDLL.dll",CharSet = CharSet.Unicode)]
  2. public static extern int GetString(StringBuilder str,int len);

在原生方面你会有@H_403_3@

  1. function GetString(str: PChar; len: Integer): Integer; stdcall;
  2. begin
  3. StrLCopy(str,'abc',len);
  4. Result := 1; // real code would have real error handling
  5. end;

然后这样调用:@H_403_3@

  1. StringBuilder str = new StringBuilder(256);
  2. int retval = GetString(str,str.Capacity);

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

  1. [DllImport("NativeDLL.dll",CharSet = CharSet.Unicode)]
  2. public static extern int GetString(out string str);

和这个本地人一样:@H_403_3@

  1. function GetString(out str: PChar): Integer; stdcall;
  2. begin
  3. str = CoTaskMemAlloc(SizeOf(Char)*(Length('abc')+1));
  4. StrCopy(str,'abc');
  5. Result := 1; // real code would have real error handling
  6. end;

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

这很容易打电话:@H_403_3@

  1. string str;
  2. int retval = GetString(out str);

猜你在找的Delphi相关文章