Get string return value from C DLL in Delphi

2019-06-25 13:18发布

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 ?

标签: c delphi dll
9条回答
时光不老,我们不散
2楼-- · 2019-06-25 13:47

As Jozz says, p2 (where you copy your string to) is never initialized in your example.

Try this instead.

var
  p1, p2 : pchar;
begin
  GetMem( p2, 255 ); // allocate memory for 'some string...'
  StrPCopy( p2, 'some string to decrypt' );
  p1 := DecryptStr( p2 );
end;

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.

查看更多
迷人小祖宗
3楼-- · 2019-06-25 13:53

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.

查看更多
仙女界的扛把子
4楼-- · 2019-06-25 14:00

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:

int  __stdcall DoSomething(char * _name);

To get it working in Delphi, I declare the following function

function DoSomething(name: PAnsiChar): integer; stdcall; external 'somedll.dll';

And then when I make the call, I have a function that looks like this:

var s: PAnsiChar;
begin
  GetMem(s, 255);
  DoSomething(s);
  // s now contains the value returned from the C DLL
end;

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..

查看更多
Emotional °昔
5楼-- · 2019-06-25 14:02

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.

查看更多
时光不老,我们不散
6楼-- · 2019-06-25 14:04

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.

查看更多
疯言疯语
7楼-- · 2019-06-25 14:06

p2 isn't initialized. StrPCopy copies the string to a random memory location. And most likely the calling convention is stdcall.

查看更多
登录 后发表回答