I have a legacy DLL written in C that contains a function that returns a string, and I need to access this function from Delphi. The only info I have about the DLL is the VB declare for accessing the function:
Public Declare Function DecryptStr Lib "strlib" (Str As String) As String
I've tried the following without success:
Declaration:
function DecryptStr(s: PChar): PChar; cdecl; external 'strlib.dll';
Usage:
var
p1, p2 : pchar;
begin
GetMem( p1, 255 );
StrPCopy( p2, 'some string to decrypt' );
p1 := DecryptStr( p2 );
end;
This consistently crashes the DLL with an Access Violation. I'm at a loss.
Any suggestions ?
As Jozz says, p2 (where you copy your string to) is never initialized in your example.
Try this instead.
Also, the memory you allocated by calling Getmem(p1,...) would have been leaked, because p1 was overwritten by the function return from DecryptStr.
However, I'd be a bit concerned about exactly what DecryptStr is returning, and who owns the memory pointed to by p1. If it's returning a pointer to memory allocated by the DLL you will need to be careful how that memory is freed.
The best way in these kind of situation is to debug your program and check the stack before and after executing the callback. How knows, it might even be a bug in the external DLL?
This way you will see pretty easy how to correct this.
I'm dropping in my solution as I've sturggled quite a bit with it and haven't found it in any of the answers.
The C++ function looks like this:
To get it working in Delphi, I declare the following function
And then when I make the call, I have a function that looks like this:
I have tried using PChar instead of PAnsiChar but all I get in return is garbage. Also, if I declare the function in Delphi with the parameter set to var , I get an exception when I try to read it.
Hope this helps anyone..
I'm guessing here, but are you sure it's cdecl? If the VB declare isn't mentioning it, I'd assume it's in fact a STDCALL function (STDCALL is quite common on Windows, as almost all of its native API uses it). Calling a function of one calling convention as if it were of another calling convention can really mess up the stack, usually leading to a crash.
Also, be sure to check whether the string is ANSI (LPSTR/LPCSTR) or UNICODE (LPWSTR/LPCWSTR). I don't know VB or Delphi, so I don't know what each one uses by default.
Was the dll written in Borland C or C++Builder by any chance with the intention of being used with Delphi? In which case it could have been compiled using a pascal directive.
p2 isn't initialized. StrPCopy copies the string to a random memory location. And most likely the calling convention is stdcall.