2

From a c app (VS2008, Win), I call a function in a dll written in Delphi in Borland. The function works, but after each call I get this error: “The value of ESP was not properly saved across a function call[…]” which means my calling convention is wrong. I don't know Delphi and I don't have the full dll code, but I believe this is the Delphi function:

function translate(file1, file2: PChar):PChar; stdcall;
    ...
    Result:=PChar(c);
end;
exports
    translate; 

The relevant part in c:

typedef char*(__stdcall *translate)(char*, char*);
translate MyTranslate;
...
MyTranslate = (translate)GetProcAddress(dll, "translate");
char* result = (*MyTranslate)(file1, file2);

Instead of __stdcall in c above I've tried __cdecl and __fastcall, but I always get the ESP message. Also, in the Dephi function code the function seems to return char*, but the dll doc says it returns "true" or "false" (?). So in c instead of "typedef char*..." I've tried "typedef BOOL...": still, I get the ESP message. I know I can suppress the message under "Basic Runtime Checks" (see here), but I'd rather get the calling syntax right. The dll is compressed with UPX, but I'm not sure if it's relevant (like I said, the function itself works).

Community
  • 1
  • 1
MrSparkly
  • 627
  • 1
  • 7
  • 17
  • If you can't get the code this is going to be tricky! It seems odd that a function from a DLL returns a `char*`. Who's responsibility is it to free that memory? – David Heffernan May 09 '11 at 08:38
  • I tried the more sensible return value, bool, too. In either case I get the ESP warning. – MrSparkly May 09 '11 at 22:29
  • Hmm ... maybe the delphi pointers are 4 bytes long and your c pointers are 8 bytes long? Can you compile for 32-bits? – pmg May 09 '11 at 23:17
  • Three thoughts: First, VS2008's C compiler probably defaults to Unicode (wide) characters, while any "Borland" Delphi app will be AnsiChar; your pointers aren't right. Second, are you compiling to a 32-bit target in your C app? Delphi versions to date are 32-bit only. Finally, are you sure of the definitions for `typedef char*(__stdcall *translate)`? Older versions of MS's C compiler used `__winapi` and `imports` defines (don't recall the exact syntax - it's been a while). – Ken White May 10 '11 at 00:32
  • @Ken: just to clarify, that's Any pre-"Delphi 2009" version for non-Unicode (ie Delphi 1-7, 2005, 2006, 2007.) Plenty of people (in my anecdotal experience :p) still refer to modern Delphi as "Borland Delphi". @MrSparkly: do you know what version of Delphi the DLL was compiled with? – David May 10 '11 at 04:19
  • Also, try stepping into the function call in CPU view and see what code the DLL has for its prolog/epilog. You may be able to deduce the calling convention and some info about its return type from that. – David May 10 '11 at 04:31
  • @DavidM, @KenWhite My target platform is Win32, pre-processor def is "WIN32", so I'm fairly sure I'm working with 32-bit. The Delphi dll is dated 5/2009, the dll doc mentions Delphi7 and Borland IDE. I don't know how valid this info is, as the doc seems to be out of sync with the actual dll. Thanks for all the suggestions, I'm working my way through them. – MrSparkly May 10 '11 at 05:27
  • 1
    You say there is a doc for the DLL. What does the doc actually say about the function in question? Does it include the actual signature of the function? – Remy Lebeau May 10 '11 at 07:51

2 Answers2

0

I believe the problem is that your Delphi function description isn't correct. All you could do is rightly mark the 'translate' function with __stdcall.

This kind of error occures when you try to invoke a COM object according to a one description and it actually has a different one. With COM objects it happends because there can be more that one version of the COM object on your machine and incorrect version is loaded. So, this is a dll-hell-like problem.

But in your case I believe that you know perfectly well where your Delphi DLL is loaded from. So I think it's just incorrect doc for that particular version of the DLL.

Nick Borodulin
  • 3,065
  • 4
  • 21
  • 21
0

If the dll is using Borland fastcall(EAX, EDX, ECX) and the compiler is using Microsoft fastcall(EAX, EDX), that could cause the ESP register to lose sync quickly.

axel22
  • 32,045
  • 9
  • 125
  • 137
gmlime
  • 1,017
  • 8
  • 17