Stdcall
Calling ConventionThis 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. It must be used to import any routine for which this convention was specified.
In the Stdcall
calling convention subprogram parameters are pushed
on the stack by the caller from right to left. The callee (and not the
caller) is in charge of cleaning 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 instance the Win32 function:
APIENTRY int get_val (long);
should be imported 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"
As for the C
calling convention, when the External_Name
parameter is missing, it is taken to be 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");
then 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");
then the imported routine is retrieve_val
, that is, 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.
It is also possible to 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.