Stdcall
Calling Convention ¶This convention, which was the calling convention used for Pascal programs, is used by Microsoft for all the routines in the Win32 API for efficiency reasons. You must use it to import any routine for which this convention was specified.
In the Stdcall
calling convention, subprogram parameters are also pushed
on the stack by the caller from right to left. However, the callee, not the
caller, is in charge of cleaning up the stack on routine exit. In addition,
the name of a routine with Stdcall
calling convention is mangled by
adding a leading underscore (as for the C
calling convention) and a
trailing @nn
, where nn
is the overall size (in
bytes) of the parameters passed to the routine.
The name to use on the Ada side when importing a C routine with a
Stdcall
calling convention is the name of the C routine. The leading
underscore and trailing @nn
are added automatically by
the compiler. For example, you could import the Win32 function:
APIENTRY int get_val (long);
from Ada as follows:
function Get_Val (V : Interfaces.C.long) return Interfaces.C.int; pragma Import (Stdcall, Get_Val); -- On the x86 a long is 4 bytes, so the Link_Name is "_get_val@4"
Like the case for the C
calling convention, when the
External_Name
parameter is missing, it is the name of the Ada
entity in lower case. If instead of writing the above import pragma
you write:
function Get_Val (V : Interfaces.C.long) return Interfaces.C.int; pragma Import (Stdcall, Get_Val, External_Name => "retrieve_val");
the imported routine is _retrieve_val@4
. However, if instead
of specifying the External_Name
parameter, you specify the
Link_Name
as in the following example:
function Get_Val (V : Interfaces.C.long) return Interfaces.C.int; pragma Import (Stdcall, Get_Val, Link_Name => "retrieve_val");
the imported routine is retrieve_val
. There is no
decoration at all; no leading underscore and no Stdcall suffix
@nn
.
This is especially important as in some special cases a DLL’s entry
point name lacks a trailing @nn
while the exported
name generated for a call has it.
You can also import variables defined in a DLL by using an import pragma for a variable. As an example, if a DLL contains a variable defined as:
int my_var;
then, to access this variable from Ada you should write:
My_Var : Interfaces.C.int; pragma Import (Stdcall, My_Var);
Note that to ease building cross-platform bindings, this convention
will be handled as a C
calling convention on non-Windows platforms.