【问题标题】:Pass string from Delphi dll to .net将字符串从 Delphi dll 传递到 .net
【发布时间】:2013-07-22 13:39:50
【问题描述】:

我已经搜索了很多关于这个问题的信息,关于如何将字符串从 delphi dll 传递到 .NET 没有明确的答案 接下来的代码基于msdn帮助文件:http://msdn.microsoft.com/en-us/library/4zey12w5.aspx

//Delphi code

function myDelphiFunc(var Buffer: PChar): Integer; export; stdcall;
  Buffer:='this is a test';
  Return:=0;
end;

//vb.NET code

<DllImport(path)> _
Public Function myDelphiFunc(ByVal buffer As String) As Integer

Public Sub myNETFunc()
  Dim buffer_size As integer = 25
  Dim buffer As String = New String(CChar(" "), buffer_size )
  Call myDelphiFunc(buffer)
  MsgBox(Strings.Left(buffer, InStr(buffer, Chr(0)) - 1))
End Sub

调用 myDelphiFunc 时,我在“缓冲区”变量中收到一个空字符串。我做错了什么?

提前致谢

【问题讨论】:

  • 对我来说很奇怪,你有一个 var 参数用于你试图返回的字符串。我对 VB 一无所知,但在我看来,您已经分配了缓冲区,因此无需从您的 Delphi DLL 返回一个新的 char 指针。但是,我决定不质疑您的设计,并发布了与您当前的 Delphi 代码兼容的答案。

标签: .net vb.net delphi pinvoke


【解决方案1】:

您的代码有很多问题。主要故障有:

  • Delphi 函数通过引用接收指针,但 VB 代码通过值传递它。
  • Delphi 代码需要将字符串复制到提供的缓冲区中。
  • Delphi 代码应该使用 PAnsiChar 来匹配 VB。或 p/invoke 上的 PWideChar 和 CharSet.Unicode。
  • VB 代码需要使用 StringBuilder 而不是 String,以便将字符串编组回调用方。
  • 该函数需要接受一个长度参数以避免缓冲区溢出。

但是,我不确定是否值得尝试深入了解它。最简单的方法是使用在共享 COM 堆上分配的 BSTR。这使得函数更易于使用,并隐藏了所有内存分配的复杂性。

德尔福

procedure TestFunc(out str: WideString); stdcall;
begin
  str := 'foo';
end;

VB

<DllImport(path)> _ 
Public Sub TestFunc(<MarshalAs(UnmanagedType.BStr)> ByRef str As String)

【讨论】:

  • +1 更好的是,如果您的 .NET 应用程序需要与 dll 进行大量交互,请将您的 dll 实现为 com 服务器,并利用 Delphi 和 .NET 提供的广泛互操作支持。跨度>
  • 这是很好的信息。我有一组 Delphi 代码,我想将它们提供给 .NET。任何提示首先阅读什么?
  • +1 感谢大卫赫弗南。我的应用程序现在运行良好。我希望这个简单的代码可以帮助其他程序员。
  • @LeonardoHerrera 你可以开始here for Delphi 和here for .NET。
【解决方案2】:

您的代码应替换为

function myDelphiFunc(var Buffer: PChar): Integer; export; stdcall;
const
  tmp = 'this is a test';
begin
  Buffer := StrAlloc(Lenght(tmp)+1);
  StrPCopy(Buffer, PChar(tmp));
  Return:=0;
end;

【讨论】:

  • 不。那是行不通的。需要在 Delphi 中删除 var。需要使用 PAnsiChar。需要在 .net 端使用 StringBuilder。在 Delphi 方面,您需要复制到提供的缓冲区中。在 Delphi 端不需要使用 export。
  • @DavidHeffernan 为什么在 CLR 基于 UTF-16 时使用 AnsiChar?如果使用 P*Char,CLR 应该如何传递给 Delphi 缓冲区?
  • @Arioch p/invoke 的默认编组是 ANSI。对 UTF16 使用 CharSet.Unicode。缓冲区长度需要一个额外的参数。以 GetWindowText 为例。在 pinvoke.net 上查找。
  • 感谢 AlexSC,最后我使用了 David Hofferman 的解决方案。
猜你喜欢
  • 1970-01-01
  • 2020-09-11
  • 1970-01-01
  • 2014-02-24
  • 1970-01-01
  • 2012-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多