Solved

Using a VC++ dll in Delph - GPF?

Posted on 1999-01-26
3
236 Views
Last Modified: 2012-05-04
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:
FindX(0,'shsh');

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!!!
0
Comment
Question by:ShadowHawk071998
  • 2
3 Comments
 
LVL 12

Accepted Solution

by:
rwilson032697 earned 400 total points
ID: 1363417
ShadowHawk:

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.

Cheers,

Raymond.
0
 

Author Comment

by:ShadowHawk071998
ID: 1363418
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.
Thanks!
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 1363419
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:

Cheers,

Raymond.



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.

0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
This Micro Tutorial hows how you can integrate  Mac OSX to a Windows Active Directory Domain. Apple has made it easy to allow users to bind their macs to a windows domain with relative ease. The following video show how to bind OSX Mavericks to …
In this video I am going to show you how to back up and restore Office 365 mailboxes using CodeTwo Backup for Office 365. Learn more about the tool used in this video here: http://www.codetwo.com/backup-for-office-365/ (http://www.codetwo.com/ba…

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now