什么是 __stdcall?

发布于 2024-07-08 17:03:01 字数 376 浏览 14 评论 0原文

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

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

我对这个 WINAPI 标识符的用途感到困惑,并发现:

#define WINAPI      __stdcall

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

I'm learning about Win32 programming, and the WinMain prototype looks like:

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

I was confused as to what this WINAPI identifier was for and found:

#define WINAPI      __stdcall

What does this do? I'm confused by this having something at all after a return type. What is __stdcall for? What does it mean when there is something between the return type and function name?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

噩梦成真你也成魔 2024-07-15 17:03:01

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

还有许多其他调用约定,__cdecl__thiscall__fastcall 以及名字奇妙的 __declspec(naked)__stdcall 是 Win32 系统调用的标准调用约定。

维基百科涵盖了详细信息

当您调用代码之外的函数(例如操作系统 API)或操作系统调用您时(如 WinMain 的情况),这一点尤为重要。 如果编译器不知道正确的调用约定,那么您可能会遇到非常奇怪的崩溃,因为堆栈将无法正确管理。

__stdcall is the calling convention used for the function. This tells the compiler the rules that apply for setting up the stack, pushing arguments and getting a return value.

There are a number of other calling conventions, __cdecl, __thiscall, __fastcall and the wonderfully named __declspec(naked). __stdcall is the standard calling convention for Win32 system calls.

Wikipedia covers the details.

It primarily matters when you are calling a function outside of your code (e.g. an OS API) or the OS is calling you (as is the case here with WinMain). If the compiler doesn't know the correct calling convention then you will likely get very strange crashes as the stack will not be managed correctly.

つ可否回来 2024-07-15 17:03:01

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

维基百科文章 概述了其中发现的不同调用约定。

C or C++ itself do not define those identifiers. They are compiler extensions and stand for certain calling conventions. That determines where to put arguments, in what order, where the called function will find the return address, and so on. For example, __fastcall means that arguments of functions are passed over registers.

The Wikipedia Article provides an overview of the different calling conventions found out there.

新一帅帅 2024-07-15 17:03:01

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

The answers so far have covered the details, but if you don't intend to drop down to assembly, then all you have to know is that both the caller and the callee must use the same calling convention, otherwise you'll get bugs that are hard to find.

债姬 2024-07-15 17:03:01

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

I agree that all the answers so far are correct, but here is the reason. Microsoft's C and C++ compilers provide various calling conventions for (intended) speed of function calls within an application's C and C++ functions. In each case, the caller and callee must agree on which calling convention to use. Now, Windows itself provides functions (APIs), and those have already been compiled, so when you call them you must conform to them. Any calls to Windows APIs, and callbacks from Windows APIs, must use the __stdcall convention.

无声情话 2024-07-15 17:03:01

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

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

It has to do with how the function is called- basically the order in which things are put on the the stack and who is responsible for cleanup.

Here's the documentation, but it doesn't mean much unless you understand the first part:
http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx

落花随流水 2024-07-15 17:03:01

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

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

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

这里的fnname有参数,它直接推入堆栈。

__stdcall is used to put the function arguments in the stack.
After the completion of the function it automatically deallocates the memory.
This is used for fixed arguments.

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

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

Here the fnname has args it directly push into the stack.

戴着白色围巾的女孩 2024-07-15 17:03:01

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

要启动线程:

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

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

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

I never had to use this before until today. Its because in my code I am using multi-threadding and the multi-threading API I am using is the windows one (_beginthreadex).

To start the thread:

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

The ExecuteCommand function MUST use the __stdcall keyword in the method signature in order for beginthreadex to call it:

unsigned int __stdcall Scene::ExecuteCommand(void* command)
{
    return system(static_cast<char*>(command));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文