【问题标题】:WINAPI identifiers in function declaration C++ in DLL entrypoint function [duplicate]DLL入口点函数中的函数声明C++中的WINAPI标识符[重复]
【发布时间】:2019-01-25 14:49:01
【问题描述】:

我只是在学习如何用 C++ 创建一个 dll

出现了这个:

BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)

我无法理解DllMain() 中的"WINAPI" 是什么?

我知道一个函数是:

typeReturn functionName (params) { function body }

typeReturn:函数返回值,
functionName:函数名,
params:函数参数,
{function body} : 是函数里面的代码。
...

那么,按照解释,WINAPI 在 C++ 中是什么意思,或者__stdcall

我不是在问WINAPI 本身是什么意思。

************更新**************

C++ 有(调用约定)用于将每个以特殊方式给出的参数放入内存。 请正确阅读问题并避免将其标记为重复,因为学习c / c ++的人需要学习而不陷入混乱

【问题讨论】:

  • 对我来说,在 Google 中搜索“WINAPI”会在第一个链接中给出答案:stackoverflow.com/questions/2348442/…
  • 是的,但是 IN C++ 是什么意思?我可以编写带有额外标识符的函数吗?

标签: c++ c winapi dll calling-convention


【解决方案1】:

WINAPI 定义为__stdcall

其实__stdcall是一个调用约定而不同的调用约定以不同的方式推送参数,下面是c/c++的一些调用约定:强>

在 x86 中:

  • C 调用约定 (__cdecl)__cdecl 调用约定的主要特点是:

    1. 参数从右到左传递,并放在堆栈上。
    2. 堆栈清理由调用者执行。
    3. 函数名称通过以下划线字符'_'作为前缀来修饰。
  • 标准调用约定 (__stdcall)__stdcall 调用约定的主要特点是:

    1. 参数从右到左传递,并放在堆栈上。
    2. 堆栈清理由被调用函数执行。
    3. 函数名称通过添加下划线字符和“@”字符以及所需的堆栈空间字节数进行修饰。
  • 快速调用约定 (__fastcall)__fastcall 调用约定的主要特点是:

    1. 需要 32 位或更少的前两个函数参数被放入寄存器 ECXEDX。其余的从右到左压入堆栈。
    2. 参数由被调用函数从堆栈中弹出。
    3. 通过在前面加上'@' 字符并附加'@' 和参数所需的字节数(十进制)来修饰函数名称。

Consider to Read This Link


在 x64 中:x64 中,仅存在__fastcall。所有其他属性都将被忽略。

x64 应用程序二进制接口 (ABI) 默认使用四个寄存器 fast-call 调用约定。


注意: 当你调用一个函数时,在汇编级别发生的事情是所有传入的参数都被压入堆栈或放入寄存器或放入静态存储中,然后程序跳转到不同的代码区域。新的代码区域查看堆栈并期望将参数放置在那里。

不同的调用约定以不同的方式推送参数。有些可能会先推送第一个参数,或者有些可能会最后推送第一个参数。或者有些人可能会将参数保存在寄存器中,根本不推送它。

通过指定调用约定,您是在告诉编译器如何推送参数。

【讨论】:

  • 所以,PARAMETERS 可以传递到堆栈,为什么?或者为什么我需要将参数推送到另一个站点?抱歉,我是 C++ 新手。
  • __cdecl 约定“更安全”,因为调用者需要释放堆栈。 __stdcall 库中可能发生的情况是开发人员可能忘记正确释放堆栈,或者攻击者可能通过破坏 DLL 的堆栈(例如通过 API 挂钩)注入一些代码,然后调用者不会检查这些堆栈。看到这个Link
  • 那么,C++ 中的“调用约定”是一种更安全的函数调用方式,可以避免一些攻击者注入代码来破坏我的函数。在谷歌搜索...
  • @AndresCamiloSierraHormiga 调用约定通常不是调用函数的“更安全”的方式。 每个函数都有一个调用约定。这是调用者和被调用者之间同意遵守的合同,以便被调用者知道在哪里可以找到它的参数以及在哪里放置它的返回值,以便调用者可以找到它。
  • 值得注意的是,这些调用约定仅与 32 位代码相关。 Windows API 的 64 位 ABI 只定义了一个调用约定,您可以不用在代码中指定一个,因为选择是明确的。
【解决方案2】:

动态链接库,用于Windows操作系统,所以在Windows上运行的DLL函数的入口点应冠以“WINAPI”。

【讨论】:

    猜你喜欢
    • 2013-08-19
    • 2016-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-27
    相关资源
    最近更新 更多