_imp 和 __imp 有什么区别?

2023-11-25

当我在 Qt Creator 中工作时尝试使用 MinGW 链接到 MSVC 编译的库时,遇到了一个有趣的错误。链接器抱怨缺少一个符号,就像_imp_FunctionName。当我意识到这是由于缺少 extern“C” 并修复它时,我还使用 /FAcs 运行 MSVC 编译器来查看符号是什么。原来,这是__imp_FunctionName(这也是我在 MSDN 和很多大师博客网站上阅读的方式)。

我对 MinGW 链接器如何抱怨以开头的符号感到非常困惑_imp,但能够很好地找到它,尽管它开头为__imp。深度编译器魔术师能否阐明这一点?我使用的是 Visual Studio 2010。


这是工作中相当简单的标识符装饰。这imp_前缀由编译器自动生成,它导出一个函数指针,允许优化与 DLL 导出的绑定。根据语言规则,imp_ 以前导下划线为前缀,这是必需的,因为它位于全局命名空间中并且由实现生成,并且不会出现在源代码中。所以你得到_imp_.

接下来发生的事情是编译器装饰标识符允许链接器捕获声明不匹配。非常重要,因为编译器无法诊断模块之间的声明不匹配,而在运行时自己诊断它们是very痛苦。

首先是 C++ 装饰,这是一个支持函数重载的非常复杂的方案。它会生成看起来非常奇怪的名称,通常包括很多?和 @ 字符,带有用于参数和返回类型的额外字符,以便重载明确。然后是 C 标识符的修饰,它们基于调用约定。 cdecl 函数有一个前导下划线,stdcall 函数有一个前导下划线和一个尾随 @n,允许在参数声明不匹配导致堆栈不平衡之前诊断它们。 64 位代码中不存在 C 修饰,(幸运的是)只有一种调用约定。

所以你得到了链接器错误,因为你忘记指定 C 链接,链接器被要求将重度修饰的 C++ 名称与轻度修饰的 C 名称相匹配。然后你用它修复了它extern "C",现在你为 cdecl 添加了一个下划线,转动_imp_ into __imp_.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

_imp 和 __imp 有什么区别? 的相关文章

随机推荐