2
votes

I have a DLL with this function signature:

function KP_RecuperarDadosFabricante(EnderecoIp, ChaveAcesso, 
  Porta: string; Return: PAnsiChar): Integer; stdcall; external 'Key.dll';

This is the sample VB.NET code from the manual of the dll:

Dim ret As Integer 
Dim ptrStr As IntPtr 
Dim DadosFab As String 

ptrStr = System.Runtime.InteropServices.Marshal.AllocHGlobal(256) 
ret = KP_RecuperarDadosFabricante("192.168.1.201", "0", "4370", ptrStr) 
DadosFab = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(ptrStr)
System.Runtime.InteropServices.Marshal.FreeHGlobal(ptrStr)

This is my Delphi code:

procedure TForm1.BitBtn1Click(Sender: TObject);
var
  Return: string;
  pReturn: PAnsiChar;
begin
  GetMem(pReturn, 512);
  FillChar(pReturn^, 512, 0);
  Memo1.Text:='';
  if KP_RecuperarDadosFabricante("192.168.1.201", "0", "4370", pReturn) = 1 then
  begin
    Return := StrPas(pReturn);
    ShowMessage(Return);
  end
  else
  begin
    ShowMessage('Error');
  end;
end;

This code works well in Delphi 7, but not works in Delphi XE. It always returns "Error". How to make this code works in Delphi XE?

1
the far directive is deprecated since... mmmm, maybe since Delphi 3 if not Delphi 1, why are you using it? what about freeing the memory you get? The vb example frees it, but your code leaks 512 bytes per call! - jachguate
@jachguate I removed "far" code, but not solved the problem. The memory is not problem yet. thanks - dataol
I didn't say it solves your problem, but they are other problems you have. - jachguate
You need to show the p/invoke declaration too. - David Heffernan
We need to see the VB code which defines KP_RecuperarDadosFabricante - David Heffernan

1 Answers

7
votes

If the DLL was written in Delphi 7, then you cannot use that DLL from Delphi XE. Even if you change the string parameters to AnsiString to make the character sizes the same, you're still stuck with the fact that the internal structure of strings changed somewhere between those versions, so the AnsiString you send from the Delphi XE code will not look the way the Delphi 7 code expects an AnsiString to look.

If you have the power to change and recompile the DLL, you should make the parameters be PAnsiChar instead, just like you'd see from nearly any other DLL on Windows. Also remember to change the final PChar parameter to PAnsiChar.


If the DLL was written in some non-Delphi language, then you might be able to fix it simply by changing the function signature. Non-Delphi languages don't have Delphi's string type, so the declaration was wrong all the time; you were just lucky when it worked from Delphi 7. Change all the parameters to have type PAnsiChar (including the final parameter); then they'll match the char* type they probably have from the original C code.