什么是 _ _ stdcall?

我正在学习 Win32编程,WinMain原型看起来像:

int WINAPI WinMain ( HINSTANCE instance, HINSTANCE prev_instance, PSTR cmd_line, int cmd_show )

我对这个 WINAPI标识符的用途感到困惑,于是找到了:

#define WINAPI      __stdcall

这是干什么的?我对在返回类型之后还有一些东西感到困惑。__stdcall是做什么的?当返回类型和函数名之间存在某种联系时,这意味着什么?

128771 次浏览

__stdcall是用于函数的调用约定。这将告诉编译器应用于设置堆栈、推送参数和获取返回值的规则。

还有许多其他的调用约定,如 __cdecl__thiscall__fastcall和名字非常好听的 __declspec(naked)__stdcall是 Win32系统调用的标准调用约定。

维基百科涵盖了 详情

当你在代码之外调用一个函数(比如 OS API)或者操作系统在调用你(就像 WinMain 的情况一样)时,这个问题就显得尤为重要。如果编译器不知道正确的调用约定,那么您可能会遇到非常奇怪的崩溃,因为堆栈将不会被正确地管理。

它必须与函数的调用方式有关——基本上就是堆栈上放东西的顺序和谁负责清理的顺序。

这是文档,但除非你理解第一部分,否则它没有多大意义:
Http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx

C 或 C + + 本身不定义这些标识符。它们是编译器扩展,代表某些调用约定。它决定将参数放在何处、以何种顺序放置、被调用的函数将在何处找到返回地址,等等。例如,_ _ fastcall 意味着函数的参数通过寄存器传递。

维基百科文章提供了不同调用约定的概述。

到目前为止,答案已经涵盖了细节,但是如果您不打算下降到汇编,那么您只需要知道调用方和被调用方都必须使用相同的调用约定,否则您将得到很难找到的 bug。

我同意到目前为止所有的答案都是正确的,但是原因是这样的。微软的 C 和 C + + 编译器为应用程序的 C 和 C + + 函数中的函数调用(预期的)速度提供了各种调用约定。在每种情况下,调用方和被调用方必须就使用哪种调用约定达成一致。现在,Windows 本身提供了函数(API) ,这些函数已经被编译,所以当您调用它们时,必须遵循它们。对 WindowsAPI 的任何调用以及来自 WindowsAPI 的回调都必须使用 _ _ stdcall 约定。

_ _ stdcall 用于将函数参数放入堆栈中。 函数完成后,它会自动释放内存。 这用于固定参数。

void __stdcall fnname ( int, int* )
{
...
}


int main()
{
CreateThread ( NULL, 0, fnname, int, int*...... )
}

这里的 姓名有它直接推送到堆栈的参数。

我以前从没用过这个,直到今天。这是因为在我的代码中,我使用的是多线程,而我使用的多线程 API 是 windows one (_ starthreadex)。

首先:

_beginthreadex(NULL, 0, ExecuteCommand, currCommand, 0, 0);

ExecuteCommand 函数 必须的在方法签名中使用 _ _ stdcall 关键字,以便 startthreadex 调用它:

unsigned int __stdcall Scene::ExecuteCommand(void* command)
{
return system(static_cast<char*>(command));
}