2013-07-22 167 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上查看。 –