Stdcall Calling Convention (GNAT User’s Guide for Native Platforms)

#### 7.4.8.3 `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.