3
votes

I have searched a lot about this issue, and there is no clear answer about how to pass a string from delphi dll to .NET Next code is based on msdn help files: 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

I receive an empty string in "buffer" variable when calling myDelphiFunc. What am I doing wrong?

Thanks in advance

2
It´s strange to me that you have a var parameter for the string you´r trying to return. I know nothing about VB, but it seems to me that you already have the buffer allocated, so no need to return a new char pointer from your Delphi DLL. However, I decided to not question your design and posted an answer compatible with you current Delphi code. - AlexSC

2 Answers

10
votes

There's lots wrong with your code. The main faults are:

  • The Delphi function receives a pointer by reference, but the VB code passes it by value.
  • The Delphi code would need to copy the string into the buffer provided.
  • The Delphi code should use PAnsiChar to match the VB. Or PWideChar and CharSet.Unicode on the p/invoke.
  • The VB code needs to use StringBuilder rather than String in order for the string to be marshalled back to the caller.
  • The function would need to accept a length parameter in order to avoid buffer overruns.

However, I'm not sure it's worth trying to understand it in too much depth. The simplest way to do this is to use a BSTR which is allocated on the shared COM heap. This makes the function much easier to use and hides all the memory allocation complexity.

Delphi

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

VB

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

Your code should be replaced by

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;