我正在学习Win32编程,WinMain
原型如下:
int WINAPI WinMain ( HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show )
我对这个WINAPI
标识符的用途感到困惑并找到了:
#define WINAPI __stdcall
这是做什么的?在返回类型之后,我对此感到困惑。什么是__stdcall
?当返回类型和函数名称之间有什么东西时,这是什么意思?
答案 0 :(得分:154)
__stdcall
是用于该函数的调用约定。这告诉编译器适用于设置堆栈,推送参数和获取返回值的规则。
还有许多其他调用约定,__cdecl
,__thiscall
,__fastcall
和精美的__naked
。 __stdcall
是Win32系统调用的标准调用约定。
维基百科涵盖details。
当您调用代码之外的函数(例如OS API)或操作系统正在调用您时(这与WinMain的情况一样),这一点非常重要。如果编译器不知道正确的调用约定,那么您可能会遇到非常奇怪的崩溃,因为堆栈将无法正确管理。
答案 1 :(得分:33)
C或C ++本身不定义这些标识符。它们是编译器扩展,代表某些调用约定。这决定了放置参数的位置,以什么顺序放置,被调用函数将在何处找到返回地址,等等。例如,__ fastcall意味着函数的参数通过寄存器传递。
Wikipedia Article概述了那里发现的不同调用约定。
答案 2 :(得分:16)
到目前为止,答案已经涵盖了细节,但是如果你不打算下载到程序集,那么你必须知道的是调用者和被调用者都必须使用相同的调用约定,否则你将会得到很难找到的bug。
答案 3 :(得分:10)
我同意到目前为止所有的答案都是正确的,但这就是原因。 Microsoft的C和C ++编译器为应用程序的C和C ++函数中的(预期)函数调用速度提供了各种调用约定。在每种情况下,调用者和被调用者必须就使用哪种调用约定达成一致。现在,Windows本身提供了功能(API),并且已经编译了这些功能,所以当你调用它们时,你必须遵守它们。对Windows API的任何调用以及来自Windows API的回调都必须使用__stdcall约定。
答案 4 :(得分:10)
答案 5 :(得分:5)
它与调用函数的方式有关 - 基本上是事物放在堆栈上的顺序以及谁负责清理。
这是文档,但除非你理解第一部分,否则它没有多大意义:
http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx
答案 6 :(得分:4)
__ stdcall用于将函数参数放入堆栈中。 完成该功能后,它会自动释放内存。 这用于固定参数。
void __stdcall fnname ( int, int* )
{
...
}
int main()
{
CreateThread ( NULL, 0, fnname, int, int*...... )
}
这里 fnname 有args它直接进入堆栈。
答案 7 :(得分:1)
启动帖子:
_beginthreadex(NULL, 0, ExecuteCommand, currCommand, 0, 0);
ExecuteCommand函数必须在方法签名中使用__stdcall关键字,以便beginthreadex调用它:
unsigned int __stdcall Scene::ExecuteCommand(void* command)
{
return system(static_cast<char*>(command));
}