【问题标题】:__stdcall - WINAPI vs STDMETHODCALLTYPE vs APIENTRY__stdcall - WINAPI vs STDMETHODCALLTYPE vs APIENTRY
【发布时间】:2020-01-14 14:33:45
【问题描述】:

我正在阅读一些游戏修复代码,它们处理内存操作以修复游戏的“问题”。我发现代码使用了 2 个,它们是WINAPISTDMETHODCALLTYPE。这些宏都被评估为__stdcall,它指定了函数的调用约定。我还发现APIENTRY 也是WINAPI 的另一个宏别名。那么这些宏之间有什么区别吗?在我看来,它们只是别名。为什么会有这么多?

【问题讨论】:

  • Windows 历史悠久,可以追溯到 16 位 Windows。这些宏在现代 32 位 Windows 中相同的事实并不意味着它们总是相同的。

标签: c++ winapi


【解决方案1】:

Windows API 中的所有数据类型和调用约定都定义为别名(预处理器宏或typedefs)。这允许稳定的 ABI,而与编译器或工具链无关。它还允许在不破坏现有代码的情况下更改 ABI(例如,当引入 64 位 Windows 时)。

WINAPISTDMETHODCALLTYPE 都扩展为相同的东西:__stdcall 用于 x86,其他任何东西都没有。那么为什么同一件事有两个别名呢?因为它们控制不同子集的调用约定:

  • WINAPI 指定基于平面 C 的 Windows API 的调用约定。
  • 另一方面,STDMETHODCALLTYPE 控制 COM 的调用约定 (Component Object Model)。

COM 和 Windows API 是独立的。有 2 个别名来控制两者的调用约定是非常有意义的。您不会因为要迁移到 Win128 的新 ABI 而破坏所有 COM。

【讨论】:

  • 那些不是拼写错误。有 API(“应用程序编程接口”),然后是 ABI(“应用程序二进制接口”)。我真的指的是我写 ABI 的地方。
【解决方案2】:

因为在 16 位中,所有这些都是不同的约定。由于 x86 平面模式,所有与 windows 相关的都是__stdcall(从右向左推,被调用者清除堆栈)。 __cdecl__fastcall 也存在。

从 x64 开始,实际上有 only one 并且所有这些都被忽略了。

许多其他 Windows 元素(如 WPARAM 和 LPARAM)也是如此。一旦 WPARAM 是 16 位,在 x86 中它们都是 32 位,而在 x64 中它们都是 64 位。

【讨论】:

    猜你喜欢
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    • 2014-08-17
    • 2011-09-18
    • 1970-01-01
    • 2012-07-27
    相关资源
    最近更新 更多