tags:

views:

72

answers:

2

Hi, I have to use an existing dll, but got a problem with it.

Here's how I try to use it:

unit u_main;

...
implementation

procedure getUserData(var User, Pass: string); stdcall; external 'Common5.dll';

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  u, p: string;
begin
   getUserData(u,p);
end;
...
end.

When I press the button the get the userData, I get an EInvalidPointer exception. The dll is registerd and in some other projects it's in use and work. any ideas?

EDIT: The DLL was created in Delphi7 and is now used in a Delphi 2009 project. Maybe there's a problem with unicode strings or something like that?

+4  A: 

You need to rebuild the Delphi 7 DLL, make it follow the WinApi standard of getting PChar and BufferLen parameters. You've got multiple problems with the current implementation:

  1. string is platform-specific, it's implementation may change between delphi versions (and did change). You're not supposed to use string outside the platform!
  2. You're passing the parameters as "var", suggesting the DLL might change the value of user and/or pass. String is an special, managed type, changing it requires allocating memory for the new string. This in turns requires you to share the memory manager between the DLL and the EXE (using sharemem.pas and BorlandMM.dll - or variants). The trouble is, sharing the memory manager between different versions of Delphi is an unsupported configuration! (gotton from embarcadero forums)
  3. The Delphi 7 is hoping to receive an simple AnsiString (1 byte chars), while the Delphi 2009 exe is sending Unicode strings (2 bytes per char).
Cosmin Prund
Thank you for this helpful information.
doubleu
@doubleu, don't tick the "answer" so fast, maybe someone else has a better idea. Allowing 24 hours for others to see the question would be good practice. Unless of course you already tested my suggestions and they solved your problem...
Cosmin Prund
+1  A: 

Along with using PChar, be sure to pre-allocate the space before you call GetUserData. i.e. if you assign 'foo' into a pchar that's empty, you'll blow up. So either use static length PChar/PAnsiChar arrays, or use this technique:

var
  s : AnsiString;
begin
  setlength(s,256);
  MyDLLProc(PAnsiChar(s));
end;
Chris Thornton