visual-c++ - _imp 和 __imp 有什么区别?

标签 visual-c++ dll linker mingw

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

我对 MinGW 链接器如何提示以 _imp 开头的符号感到非常困惑。 , 但可以很好地找到它,尽管它以 __imp 开头.一位深度编译器魔术师能否对此有所了解?我使用了 Visual Studio 2010。

最佳答案

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

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

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

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

关于visual-c++ - _imp 和 __imp 有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11236789/

相关文章:

linker - 如何在 GCC 中链接不以 lib 开头的库文件?

c++ - 与 gfortran 链接时未定义对 `std::chrono::_V2::system_clock::now()' 的引用

c++ - 在 Visual Studio C++ 系统 ("pause"中使用 freopen() 时)不工作

c++ - C++11 是否允许(不需要)释放/获取 volatile 关键字的语义

c++ - header 和链接器错误的问题(C++ 新手)

c++ - 即使 EXE 没有直接使用符号,如何强制 DLL 依赖?

c++ - 在 C++ DLL 中使用全局变量

c# - 创建用于 C# 程序的 CPP DLL

c++ - 将导出的符号保留在共享库中

visual-c++ - 我们如何消除光照噪声?