Using a VC++ dll in Delph - GPF?

Hello guys.
I'm not sure whether this is a delphi or a VC problem, but I think it is a delphi one.
My setup is : A dll written in VC++, and a program written
in delphi, using it.
First I wrote one program, which used the dll, and it worked fine. Then I wrote ANOTHER program, which also used the same dll, and some of the functions worked great. But then I called one function, and got a General Protection error (this is the message:
'XBuilder caused an exception 10H in module <unknown> at
0000:00cc1f3b... etc'). XBuilder is my delphi app name'.
I tried to narrow the problem down. So I went to the declaration of the function, and made it empty (only remarks). THen I called it, same problem. I traced the problem with both the delphi and the VC++. The VC++ worked great, and the problem is AFTER the call to the function.
THe delphi works okay on the line calling the function, the bug starts on the NEXT line.
THen I tried to call other functions, and some worked great, some caused the same GPF.
I tried to check for c'tors or d'tors, or any code that might be invoked in the DLL, but The problem isn't there. It's as if the problem is within the delphi code. I just can't think of anything, because my OTHER delphi program, using the SAME dll works great!
what can I do?

Some more info:
1. I'm using delphi 3
2. Tried it on 2 computers, one running win98, and one running winNT, and it gets the same error on both.
3. I once had the same problem (In my buggy program). I called a function after pressing a speed button. I then moved from a speed button to a normal button, and the problem disappeared (!!!). I though 'okay, maybe delphi has some bug in speedbuttons'. But now I get the bug even if I call the function from my 'main'.
4. The declaration of the function in the dll looks like:

extern "C" void __cdecl FindX(int P, char *str)

and the declaration in the DELPHI code looks like:

procedure FindX(P:Integer;str:Pchar);
stdcall; external DllLoc;

and the CALL from the delphi looks like this:

5. I searched for code in the new delphi application. I looked for initializtion parts on certain units, but the problem was not there.

So what do I do? How can I trace this problem? It suddenly happens with lots of functions from the dll. But only from my 'special' new delphi program! please help!!!
Who is Participating?
rwilson032697Connect With a Mentor Commented:

I think the problem is with this line (the calling conventions do not match...):

procedure FindX(P:Integer;str:Pchar);
    stdcall; external DllLoc;

it should read:

procedure FindX(P:Integer;str:Pchar);
    cdecl; external DllLoc;

Or you can change the function in the DLL to be __stdcall.


ShadowHawk071998Author Commented:
Hey, Thanks!
This actually worked, and worked great.
But I still wonder. How come it worked many times before (In my previous program, I used the same calls and it worked great) and only now it seemed to generate those GPF?
And I saw that it worked okay IN the C++ itself, but the bug was AFTER the call.
If you can shed some light on all this 'call' subject, I'd be very grateful.
Calling conventions alter the way arguments are passed, and how stack frames are destroyed. Some conventions require the caller to clean up the stack, some require the called function to do it. Some of the interactions you get mean that the function calls OK, and does its job correctly, but either a failure to destroy a stack frame, or an attempt to destroy it twice can lead to nasty consequences.

I guess you were just lucky with your previous program!

Here's the clip from the Delphi help:



When you declare a procedure or function, you can specify a calling convention using one of the directives register, pascal, cdecl, stdcall, and safecall. For example,

function MyFunction(X, Y: Real): Real; cdecl;


Calling conventions determine the order in which parameters are passed to the routine. They also affect the removal of parameters from the stack, the use of registers for passing parameters, and error and exception handling. The default calling convention is register.

The register and pascal conventions pass parameters from left to right; that is, the leftmost parameter is evaluated and passed first and the rightmost parameter is evaluated and passed last. The cdecl, stdcall, and safecall conventions pass parameters from right to left.
      For all conventions except cdecl, the procedure or function removes parameters from the stack upon returning. With the cdecl convention, the caller removes parameters from the stack when the call returns.

The register convention uses up to three CPU registers to pass parameters, while the other conventions pass all parameters on the stack.
      The safecall convention implements COM error and exception handling.

The table below summarizes calling conventions.

Directive      Parameter order      Clean-up      Passes parameters in registers?
register      Left-to-right      Routine      Yes
pascal      Left-to-right      Routine      No
cdecl      Right-to-left      Caller      No
stdcall      Right-to-left      Routine      No
safecall      Right-to-left      Routine      No
The default register convention is the most efficient, since it usually avoids creation of a stack frame. The cdecl convention is useful when you call functions from DLLs written in C or C++, while stdcall and safecall are used for Windows API calls. The safecall convention must be used for declaring dual-interface methods. The pascal convention is maintained for backward compatibility. For more information on calling conventions, see Program control.

The directives near, far, and export refer to calling conventions in 16-bit Windows programming. They have no effect in 32-bit applications and are maintained for backward compatibility only.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.