This page currently has details about calling conventions on the x86 platform only. The focus is on calling conventions encountered while programming in the Windows world.
What are calling conventions
Direct quote from the Wikipedia article:
A calling convention is a scheme for how subroutines receive parameters from their caller and how they return a result; calling conventions can differ in:
- Where parameters and return values are placed (in registers; on the call stack; a mix of both)
- The order in which parameters are passed (or parts of a single parameter)
- How the task of setting up for and cleaning up after a function call is divided between the caller and the callee
- Which registers that may be directly used by the callee may sometimes also be included (otherwise regarded as an ABI-detail).
- Which registers are considered to be volatile v. non-volatile and, if volatile, need not be restored by the callee
Different programming languages use different calling conventions, and so can different platforms (CPU architecture + operating system).
- Calling Conventions: MSDN article with details about calling conventions in Microsoft's Visual C/C++ compiler
When the callee cleans the arguments from the stack it needs to be known at compile time how many bytes the stack needs to be adjusted. Therefore, calling conventions that belong to the "callee clean-up" category are not compatible with variable argument lists (e.g.
- stdcall is a calling convention on the x86 platform
__stdcallis used by the entire Windows API! The preprocessor macro
WINAPI, often seen to mark Windows API functions, resolves to
__stdcall. Note that strictly speaking one should not rely on the fact that
__stdcall- it's an implementation detail that might change "any time".
- stdcall is "Callee clean-up" (e.g. varargs are not possible)
- The VC++ compiler marks up stdcall functions with the keyword
- cdecl is a calling convention on the x86 platform
- cdecl originates from the C programming language, hence its name
- cdecl is the standard calling convention for functions in C, and non-member and static member functions in C++. Despite this "standard", different compilers have different interpretations of how cdecl should be implemented. If the same program is compiled with 2 different compilers, or the same compiler but on 2 different OS platforms, the 2 compilation results may very well be incompatible.
- cdecl is "Caller clean-up" (e.g. varargs are possible)
- The VC++ compiler marks up cdecl functions with the keyword
Note: The use of
extern "C" in C++ code (to prevent name mangling) is not directly related to the use of
cdecl (or any other calling convention), and the two concepts should not be mixed. It's just a "coincidence" that
extern "C" is usually applied to global C-style functions and that those functions by default use the
cdecl calling convention.
- thiscall is used for calling C++ non-static member functions
- The name of the calling convention stems from the fact that behind the scenes the compiler adds an argument to the function parameters that contains the
thispointer, i.e. the pointer to the C++ object that receives the method call
- There are different versions of thiscall, depending on the compiler (e.g. GCC, VC++) and also on whether or not the member function being called uses variable arguments
- thiscall is both "Caller clean-up" and "Callee clean-up", depending on the use of varargs by the member function being called
- The VC++ compiler marks up thiscall functions with the keyword
Calling conventions and VC++
- In a VC++ project, if a a function does not have an explicit calling convention it uses the default calling convention defined for the project (or the file)
- In Visual Studio 2010 the project-wide default can be found in the project's properties dialog under "Configuration Properties > C/C++ > Advanced > Calling Convention"
- If the project does not explicitly set a a calling convention, it inherits the default
This is the syntax for declaring a function prototype with a calling convention:
ReturnType CallingConvention FunctionName(ParameterList);
int __stdcall DoIt(const char* foobar);
If a function pointer is defined (e.g. for callback functions, or if
GetProcAddress() is used), it also requires that a calling convention is used for the function pointer type declaration.
typedef int (__stdcall *FUN_DoIt) (char* foobar);
If a native function is invoked from .NET via P/Invoke, the P/Invoke declaration needs to include the calling convention. If the calling convention is omitted, the default is
CallingConvention.Winapi (which at runtime resolves to different calling conventions, depending on the platform that the code is executing on).
[DllImport("kernel32.dll", SetLastError=true, CallingConvention=CallingConvention.Winapi)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool Beep(uint dwFreq, uint dwDuration);