_imp和__imp有什么区别? [英] What is the difference between _imp and __imp?

查看:772
本文介绍了_imp和__imp有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我在Qt Creator中尝试使用MinGW链接到MSVC编译的库时遇到了一个有趣的错误.链接器抱怨缺少符号,类似于_imp_FunctionName.当我意识到这是由于缺少extern"C"导致的,并对其进行了修复时,我还使用/FAcs运行了MSVC编译器,以查看符号是什么.事实证明,这是__imp_FunctionName(这也是我在MSDN和许多大师博客的网站上阅读的方式).

I came across an interesting error when I was trying to link to an MSVC-compiled library using MinGW while working in Qt Creator. The linker complained of a missing symbol that went like _imp_FunctionName. When I realized That it was due to a missing extern "C", and fixed it, I also ran the MSVC compiler with /FAcs to see what the symbols are. Turns out, it was __imp_FunctionName (which is also the way I've read on MSDN and quite a few guru bloggers' sites).

对于MinGW链接器如何抱怨以_imp开头的符号,我感到非常困惑,但是尽管它以__imp开头,却能够很好地找到它.深入的编译器魔术师能否对此有所启发?我使用了Visual Studio 2010.

I'm thoroughly confused about how the MinGW linker complains about a symbol beginning with _imp, but is able to find it nicely although it begins with __imp. Can a deep compiler magician shed some light on this? I used Visual Studio 2010.

推荐答案

这是工作中非常简单的标识符修饰. imp_前缀由编译器自动生成,它导出一个函数指针,该指针可以优化对DLL导出的绑定.根据语言规则,imp_前面加一个下划线作为前缀,这是必需的,因为它位于全局名称空间中,并由实现生成,并且否则不会出现在源代码中.这样您会得到_imp_.

This is fairly straight-forward identifier decoration at work. The imp_ prefix is auto-generated by the compiler, it exports a function pointer that allows optimizing binding to DLL exports. By language rules, the imp_ is prefixed by a leading underscore, required since it lives in the global namespace and is generated by the implementation and doesn't otherwise appear in the source code. So you get _imp_.

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

Next thing that happens is that the compiler decorates identifiers to allow the linker to catch declaration mis-matches. Pretty important because the compiler cannot diagnose declaration mismatches across modules and diagnosing them yourself at runtime is very painful.

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

First there's C++ decoration, a very involved scheme that supports function overloads. It generates pretty bizarre looking names, usually including lots of ? and @ characters with extra characters for the argument and return types so that overloads are unambiguous. Then there's decoration for C identifiers, they are based on the calling convention. A cdecl function has a single leading underscore, an stdcall function has a leading underscore and a trailing @n that permits diagnosing argument declaration mismatches before they imbalance the stack. The C decoration is absent in 64-bit code, there is (blessfully) only one calling convention.

因此,由于您忘记了指定C链接,因此出现了链接器错误,因此链接器被要求将装饰严谨的C ++名称与修饰程度不高的C名称进行匹配.然后,用extern "C"进行了修复,现在为cdecl添加了一个下划线,将_imp_转换为__imp_.

So you got the linker error because you forgot to specify C linkage, the linker was asked to match the heavily decorated C++ name with the mildly decorated C name. You then fixed it with extern "C", now you got the single added underscore for cdecl, turning _imp_ into __imp_.

这篇关于_imp和__imp有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆