9

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

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

4

1 回答 1

30

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

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

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

所以你得到了链接器错误,因为你忘记指定 C 链接,链接器被要求将重修饰的 C++ 名称与轻度修饰的 C 名称相匹配。然后extern "C"_imp___imp_.

于 2012-06-28T12:02:25.567 回答