2006. január 31., kedd

Calling conventions and DLLs


Problem/Question/Abstract:

How do I call a method in a DLL written in either C or C++? What do you mean by calling conventions?

Answer:

In Delphi, when we declare a procedure or function, we can specify a convention using one of the directives register, pascal, cdecl, stdcall, and safecall. All these conventions determine the order in which parameters are passed to the procedure/function.

Let me briefly explain what these conventions mean. All the calling conventions make use of stack to pass parameters back and forth except the Register convention.

Register/Pascal

These conventions pass parameters (of procedure/function) from left to right. The leftmost parameter is evaluated and passed first and the rightmost parameter is evaluated and passed last.

And the "Register" calling convention makes use of CPU registers and hence it’s faster than other conventions. When you use this convention, there will not be any stack creation at runtime if the parameters are less than or equal to three. If the parameters are more than three, then the remaining parameters will use the stack.

This "Register" convention is the default in Delphi and it’s the efficient of all because it does not create/use the stack at runtime.

The "Pascal" convention is used for backward compatibility.

The stack cleanup process will be done automatically for all the conventions when the call returns except "Cdecl".

Cdecl/stdcall/safecall

These conventions pass parameters from right to left.  The rightmost parameter is evaluated and passed first
and the leftmost parameter is evaluated and passed last. With this convention, the caller has to remove the parameters from the stack when the call returns. So it's the responsibility of the caller.

Why am I writing these simple things in detail?

Yes. This will be very helpful when you write DLL either in Delphi and access it in Delphi Or accessing a DLL written in other languages.

When you write a function/procedure in a DLL in Delphi, you will be specifying the calling convention for each. Also when you call those functions/procedures from an application through either the static loading or dynamic loading, you need to specify the type of calling convention.

When you call a DLL written in either C or C++, you have to use the "cdecl" convention. Otherwise, you
will end up in "Access violation" problems and sometimes the application may crash. Also the DLL, you are calling, should be on the search path.

I faced a problem in my project just because of this calling convention. In my application, I need to call a method in a C DLL. I copied the DLL into my machine. Then I declared all the methods in the DLL in Delphi and tried to call one of them. When I try to access a method, I got "Access violation"; sometimes the application hung and sometimes the entire application crashed. Finally I looked into the Delphi help and got the solution with the calling convention. So I declared each method in the DLL in Delphi with the "cdecl" directive. It worked fine. So don’t forget to add this directive in each method call from a DLL written in C/C++.

Nincsenek megjegyzések:

Megjegyzés küldése