Next: , Previous: C Calling Convention, Up: Windows Calling Conventions


F.6.2 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. 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@4, that is, there is no trailing underscore but the appropriate @nn is always added at the end of the Link_Name by the compiler.

Note, that in some special cases a DLL's entry point name lacks a trailing @nn while the exported name generated for a call has it. The gnatdll tool, which creates the import library for the DLL, is able to handle those cases (see Using gnatdll for the description of the switches).

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.