2013-07-22 168 views
2

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

//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时,我在“buffer”变量中收到一个空字符串。我究竟做错了什么?

在此先感谢

+0

It's怪我,你的字符串找你试图返回一个变量参数。我对VB一无所知,但在我看来,你已经分配了缓冲区,所以不需要从你的Delphi DLL中返回一个新的字符指针。不过,我决定不要质疑你的设计,并发布一个与你目前的Delphi代码兼容的答案。 – AlexSC

回答

9

更换有很多你的代码错误。主要缺点是:

  • 德尔福功能通过引用接收指针,但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) 
+2

+1更好,如果您的.NET应用程序需要与dll进行交互,那么您需要将dll作为com服务器来实现,并利用Delphi和.NET提供的广泛的interop支持。 –

+0

这是很棒的信息。我有一套我想提供给.NET的Delphi代码。任何提示什么先阅读? –

+1

+1谢谢David Heffernan。我的应用程序现在工作完美。我希望这个简单的代码可以帮助其他程序员。 – user1361263

0

您的代码应该由

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; 
+0

没有。这是行不通的。需要在Delphi中删除var。需要使用PAnsiChar。需要在.net端使用StringBuilder。而在德尔福方面,你需要复制到提供的缓冲区。德尔福方面不需要使用出口。 –

+0

@DavidHeffernan为什么AnsiChar在CLR时基于UTF-16?如果使用P * Char,CLR应该如何传递给Delphi缓冲区len? –

+0

@Arioch p/invoke的默认编组是ANSI。使用UTF16的CharSet.Unicode。缓冲区长度需要额外的参数。例如,根据GetWindowText。在pinvoke.net上查看。 –