Get return string value from C DLL in Delphi

I have an outdated DLL written in C that contains a function that returns a string, and I need to access this function from Delphi. The only information I have about the DLL is the VB declaration to access the function:

Public Declare Function DecryptStr Lib "strlib" (Str As String) As String

I tried the following without success:

Declaration:

function DecryptStr(s: PChar): PChar; cdecl; external 'strlib.dll'; 

Using:

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

This sequentially results in access violation DLL failure. I'm at a loss.

Any suggestions?

+4
source share
9 answers

Consider rewriting the test code as follows:

 var p1, p2 : pchar; begin GetMem( p1, 255 ); // initialize GetMem( p2, 255 ); StrPLCopy( p2, 'some string to decrypt', 255 ); // prevent buffer overrun StrPLCopy( p1, DecryptStr( p2 ), 255); // make a copy since dll will free its internal buffer end; 

If you still cannot make the DecryptStr call, carefully read http://support.microsoft.com/kb/187912 .

+5
source

p2 is not initialized. StrPCopy copies the string to a random memory location. And, most likely, the calling convention is stdcall.

+4
source

I guess here, but are you sure this is cdecl? If the VB declaration does not mention this, I would suggest that this is actually a STDCALL function (STDCALL is quite common on Windows, since almost all of its own APIs use it). A function call of one calling convention, as if it were another call, can really mess up the stack, which usually leads to a crash.

Also, be sure to check if the string is ANSI (LPSTR / LPCSTR) or UNICODE (LPWSTR / LPCWSTR). I do not know VB or Delphi, so I do not know what everyone uses by default.

+2
source

As Jozz says, p2 (where you copy your line) 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; 

In addition, the memory that you allocated by calling Getmem (p1, ...) would have been leaked because p1 was overwritten by the return from DecryptStr function.

However, I would be a little worried about what DecryptStr returns, and who owns the memory pointed to by p1. If it returns a pointer to the memory allocated by the DLL, you need to be careful how this memory is freed.

+1
source

I agree with CesarB, try declaring it with the stdcall directive as:

 function DecryptStr(s: PChar): PChar; stdcall; external 'strlib.dll'; 

if it doesn't work, post the VB expression here.

0
source

The best way in this situation is to debug your program and check the stack before and after the callback. As you know, this may be an error in the external DLL?

This way you will see quite easily how to fix it.

0
source

Was the DLL written in Borland C or C ++ Builder, by chance, for use with Delphi? In this case, it could be compiled using the pascal directive.

0
source

Suggestions that lines should be "initialized" seem correct. This is because C will require the transmitted string to be completed with a zero mark. Make sure that the character in the buffers immediately after the end of the text is zero (# 0).

Why do you assume that the string passed inside is exactly 255 characters? You need to highlight Length (p1) + 1 bytes - for characters in p1 and # 0 char at the end.

Also, your sample code seems confusing regarding the use of p1 and p2. It looks like p1 is the buffer passed to the DLL that you are assigning, and p2 is the return string that the DLL allocates. But then the code will be (note the use of p1 and p2)

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

Improved variable names will help you make this clearer.

0
source

I reject my decision, as I cheated on him a bit and did not find it in any of the answers.

The C ++ function is as follows:

 int __stdcall DoSomething(char * _name); 

To make it work 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 tried using PChar instead of PAnsiChar, but all I get in return is trash. Also, if I declare a function in Delphi with the parameter set to var, I get an exception when I try to read it.

Hope this helps anyone.

0
source

All Articles