什么是__stdcall?

时间:2008-11-18 02:15:39

标签: c winapi calling-convention stdcall

我正在学习Win32编程,WinMain原型如下:

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

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

#define WINAPI      __stdcall

这是做什么的?在返回类型之后,我对此感到困惑。什么是__stdcall?当返回类型和函数名称之间有什么东西时,这是什么意思?

8 个答案:

答案 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)

直到今天我才从未使用过这个。因为在我的代码中我使用的是多线程,而我使用的多线程API是windows one(_beginthreadex)。

启动帖子:

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

ExecuteCommand函数必须在方法签名中使用__stdcall关键字,以便beginthreadex调用它:

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