DLL使用__stdcall而不进行名称修饰:为什么它甚至可以工作?

斯特凡

如果我声明这样的函数:

#ifdef TEST_EXPORTS
#define TEST_API __declspec(dllexport)
#else
#define TEST_API __declspec(dllimport)
#endif

TESTAPI int __stdcall myadd(int a, int b);

DLL中的符号是_myadd@8,对我来说很有意义(经过几个小时的阅读其他问题后,)。

但是Windows库似乎做了一些不同的事情。它们也使用__stdcall(伪装为WINAPI),但是DLL中的符号没有名称修饰。如果以上方法在Windows libs中的哪个位置,则符号为myadd

我的猜测是,他们使用def文件为符号添加别名。但是,当我链接到这些DLL之一时,为什么我的链接器知道这一点?

Windows头文件使用来声明这些函数WINAPI,因此,如果我调用它们,则链接器应查找修饰后的名称,因为它是一个__stdcall函数。但是,链接器不知何故知道删除名称修饰。

我试图通过编写一个小的DLL并使用def文件删除名称修饰来复制此内容。正如预期的那样,由于链接器仍在寻找修饰的名称,因此出现链接器错误。我已经在纯C语言中做到了这一点,以确保c ++名称修饰不会影响它。

编辑:澄清一下,MSVC 14.0 / VS2015,32位

Ari0gn

这里几乎没有记载的魔术在起作用。让我们看一些WIN32 API功能,例如RegQueryValueExWwinreg.h文件中定义如下:

WINADVAPI LSTATUS APIENTRY RegQueryValueExW(...);

哪里WIADVAPI__declspec(dllimport)APIENTRY是为一个绰号__stdcall命名约定。另请注意,标头中的所有函数都声明为extern "C"因此,无论如何,此函数应使用名称修饰,并且其DLL导出应为_RegQueryValueExW@24但是,当我们advapi32.dll使用dumpbin /exports命令查看导出时,我们看到一个未修饰的名称:

advapi出口

现在,advapi32.lib使用dumpbin /headers advapi32.lib命令仔细检查文件

在此处输入图片说明

请注意说明undecorate符,该说明符允许将修饰名称链接到未修饰的导出。您可以使用def带有EXPORTS包含未修饰名称的节文件来为dll获得相同的结果请参见文章和这个答案的其他信息。

同样,以上所有内容仅对x86应用程序有效。x64位环境中的C函数链接时没有名称修饰

C函数的修饰形式取决于其声明中使用的调用约定,如下表所示。这也是声明C ++代码具有外部“ C”链接时使用的修饰格式。默认的调用约定是__cdecl。请注意,在64位环境中,未修饰功能。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

DLL 导出 __stdcall 没有 DEF 文件和使用 VS 修饰的函数名称

为什么变量可以在Julia宏名称修饰中以#开头?

为什么我的撤回功能甚至可以工作?语法混乱

为什么不进行交换?

为什么可以键入别名函数并在不进行强制转换的情况下使用它们?

有什么方法可以让枚举保存通用对象并稍后访问它而不进行类型转换?

为什么文件全局不进行分词?

GEKKO为什么不进行初始测量?

为什么不进行比较就返回假?

使用_stdcall将更改dll中导出函数的名称

为什么我的代码运行相同的列表,即使它甚至没有被使用?

将C ++函数名称打印到C而不进行修饰

如何获取所有工作表名称而不进行修整?

当List <>在C#7.2中具有“ in”参数修饰符时,为什么仍可以修改它?

为什么在出现参数错误时不使用修饰的函数的名称?

为什么在paintComponent()中使用gif动画时不进行动画处理?

为什么在WPF中坚持使用TextBox Border Color而不进行更改?

为什么超文本传输协议甚至允许使用 GET 请求进行更改?

请告知错误是什么...为什么不进行编译?

为什么在where子句中使用范围类型变量的此函数为什么不进行typecheck?

如何自动从未修饰的stdcall DLL生成导入库?

为什么使用此修饰功能可以获得多个输出?

为什么要使用__stdcall作为函数指针

WebSockets ping / pong,为什么不进行TCP keepalive?

为什么此@Transactional方法不进行多次保存

为什么这里不进行隐式转换?

为什么不进行屏幕外更新的UICollectionViewCells?

为什么不进行这种简单的Morte程序类型检查?

为什么在选择模型之前不进行模型调整?