何时使用调用约定 [英] When to use calling conventions

查看:26
本文介绍了何时使用调用约定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用不同调用约定的关键因素是什么?有人什么时候知道在不同场合使用特定的调用约定,例如 __cdecl__stdcall__fastcall.

What are the key factors on using different calling conventions? When does someone know to use specific calling conventions such as __cdecl or __stdcall or __fastcall in different occasions.

示例会非常有用.

推荐答案

大多数时候您无需担心.通常您会使用 __cdecl,但这只是因为这是 Visual C++ 中的默认值.但是,C++ 成员函数在 Visual C++ 中默认使用 __thiscall 约定

Most of the time you don't need to worry about it. Usually you'll use __cdecl, but only because that's the default in Visual C++. C++ member functions, however, use the __thiscall convention by default in Visual C++

当您将回调传递给 API 函数(例如 Windows API 中的那些)时,您真正需要担心调用约定的(相当常见的)情况是:

A (rather common) situation where you really have to worry about calling conventions is when you pass callbacks to API functions, like those in the Windows API:

// CALLBACK is #define'd as __stdcall 
LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg 
    WPARAM wParam, LPARAM lParam); 
// ... 
windowClass.lpfnWndProc = &MyWndProc; 
::RegisterClass(&windowClass);

在这里,我们将 MyWndProc() 声明为具有 __stdcall 约定(CALLBACK#define'd如 __stdcall).这是必需的,因为操作系统期望 lpfnWndProc 指向 WNDPROC使用CALLBACK约定.

Here, we declare MyWndProc() as having the __stdcall convention (CALLBACK is #define'd as __stdcall). This is needed because the operating system expects that lpfnWndProc points to a WNDPROC, which uses the CALLBACK convention.

几乎每个接受回调的 Windows API 函数都要求回调函数使用 __stdcall 约定,并且由于 __cdecl 通常是默认值,因此您必须明确说明(对于窗口过程,您将使用 CALLBACK).

Just about every Windows API function that accepts a callback requires the callback functions to use the __stdcall convention, and since __cdecl is usually the default, you must make this explicit (you would use CALLBACK for window procedures).

这非常重要,因为如果操作系统尝试调用非__stdcall 函数,可能会发生堆栈损坏.不幸的是足够多的人得到这个错误是 Windows将实际检查调用专门针对窗口过程的约定不匹配.

This is extremely important because stack corruption can occur if the operating system attempts to call a non-__stdcall function. Unfortunately enough people get this wrong that Windows will actually check for calling convention mismatch specifically for window procedures.

虽然传递给 WinAPI 函数的回调函数需要 __stdcall,但接受可变数量参数的函数必须使用 __cdecl 调用约定,因为只有调用者知道如何从堆栈中正确弹出可变数量的参数.由于 __cdecl 通常是默认值,因此您无需为接受可变数量参数的函数显式指定 __cdecl.

While __stdcall is required for callback functions passed to WinAPI functions, functions that accept a variable number of arguments must use the __cdecl calling convention, because only the caller will know how to properly pop the variable number of arguments off the stack. Since __cdecl is usually the default, you don't need to explicitly specify __cdecl for functions that accept a variable number of arguments.

我个人还没有发现 __fastcall 的用途,尽管我确定有人有.

I personally haven't found a use for __fastcall, although I'm sure someone has.

__clrcall 仅在您与托管代码交互时才相关.

__clrcall is relevant only if you're interacting with managed code.

这篇关于何时使用调用约定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆