今天在论坛上看到一位朋友问了一个如下的问题:
#define CALLBACK __stdcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY WINAPI
#define APIPRIVATE __stdcall
#define PASCAL __stdcall
问题:
上面是这些宏的定义,但是不是很明白这些宏到底有什么用。 只是模模糊糊的知道这些关系到动态库的调用协议。
这位朋友提出的问题其实就是关于函数调用约定(Function Calling Convention)的问题。
为了搞清这个问题,最好的办法就是read MSDN !
From MSDN:
Calling Conventions
The Visual C/C++ compiler provides several different conventions for calling internal and external functions. Understanding these different approaches can help you debug your program and link your code with assembly-language routines.
The topics on this subject explain the differences between the calling conventions, how arguments are passed, and how values are returned by functions. They also discuss naked function calls, an advanced feature that enables you to write your own prolog and epilog code.
The following calling conventions are supported by the Visual C/C++ compiler.
__stdcall
Microsoft Specific
The __stdcall calling convention is used to call Win32 API functions. The callee cleans the stack, so the compiler makes vararg functions __cdecl. Functions that use this calling convention require a function prototype.
The following list shows the implementation of this calling convention.
__cdecl
Microsoft Specific
This is the default calling convention for C and C++ programs. Because the stack is cleaned up by the caller, it can do
vararg functions. The __cdecl calling convention creates larger executables than __stdcall, because it requires each function call to include stack cleanup code.
The following list shows the implementation of this calling convention.
More details see MSDN :)
我们初次在写Windows程序的时候都会先学习下面这个程序:
这里我们就会到看函数声明中有一个WINAPI宏,我们按F12后会发现其定义如下:
#define WINAPI __stdcall
调用约定(Calling convention):决定函数参数传送时入栈和出栈的顺序,栈内容由谁清除。缺省是__cdecl。
stdcall调用意味着:
1)参数从右向左压入堆栈。
2)函数自身维护堆栈,退出时清空堆栈。(cdecl由调用者清空堆栈,正因如此,实现可变参数的函数只能使用cdecl调用约定)
问题:
除了那些可变参数的函数调用外,其余的一般都是__stdcall约定。但C/C++编译默认的是__cdecl约定。所以如果在VC等环境中调用__stdcall约定的函数,必须要在函数声明时加上__stdcall修饰符,以便对这个函数的调用是使用__stdcall约定(如使用DELPHI编写的DLL时候)
下面是网上一位朋友总结的关于函数调用约定的文章,分析的很详细。我将其整理如下:
stems from:http://blog.vckbase.com/arong/archive/2004/06/09/409.html
欢迎对calling conventions有不同见解的朋友在此留言讨论!