2012-07-12 27 views
2

VB代码无法从德尔福得到PChar类型2007 DLL到Visual Basisc应用(有垃圾)

我有DLL函数decalration在我的VB应用程序代码:

Declare Function TstCharReturn Lib "myLib" Alias "TstCharReturn" (ByVal c As System.Text.StringBuilder) As Boolean 

这是代码该功能

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
    Dim s As String 
    Dim builder As New System.Text.StringBuilder 

    r = TstCharReturn(builder) 
    LogIt(s) 
    LogIt(r) 
End Sub 

电话我recomendation使用StringBuilder,而不是字符串,因为String是IMMU表,但两者都以相同的方式工作。

德尔福DLL的代码:

Function TstCharReturn (var c: pchar) : Boolean; stdcall; 
var 
BuffSize: Integer; 
sOut: string; 
begin 

    sOut:='abcdefghijklmnoprst'; 
    BuffSize:=SizeOf(Char)*(Length(sOut)+1); 
    getmem(c, BuffSize); 
    FillChar(c^,BuffSize,0); 
    Result := Length(sOut)>0; 

    if Result then 
    begin 
    Move(sOut[1], PChar(c)^, BuffSize); 
    end; 

end; 

我在VB中输出了乱码。什么是问题? 还有一个问题。如果我使用GetMem,我必须在某处释放内存,否则VB会这样做? VB6和VB2010之间有什么区别,因为我需要我的DLL与两个工作?

回答

0

你的delphi程序是错误的。你不能为返回的字符串分配新的内存,你已经有了一个指向它的指针,它在c中传递,你必须从该指针开始填充。您将需要引入另一个参数来传递该缓冲区的大小。

所以,你将有:

Declare Function TstCharReturn Lib "myLib" Alias "TstCharReturn" _ 
    (ByVal c As System.Text.StringBuilder, _ 
     ByVal cchSize As Integer) As Boolean 

和:

Dim sb As New System.Text.StringBuilder(50) 'Buffer capacity: 50 
TstCharReturn(sb, sb.Capacity) 

不要以为StringBuilder的将被神奇地传递到非托管代码的东西,它可以接受任意数据量。您需要确保初始容量,这是该过程可用的大小。

+2

Delphi代码也需要改变,以便通过值传递PChar,即char *,而不是var。 – 2012-07-12 19:03:19

+1

您还需要通过使用参数上的MarshalAs(UnmanagedType.LPStr)属性或将DLLImport的Charset属性设置为Charset来告诉PInvoke将'StringBuilder'编组为Ansi而不是Unicode .Ansi'。 – 2012-07-12 21:14:20

+0

@Remy p/invoke的默认字符集是'Charset.Ansi',当然这在C#中是真实的,我没有理由不在VB.net中。或者我错了? – 2012-07-13 08:16:33