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. 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
@`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
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:
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.