在C++中,由于重载等技术的存在,编译器要将函数、结构体、类等等的信息传递给链接器,就不能像C语言那样简单地通过函数名来完成,它需要提供额外的参数信息,而还要和C语言共用链接器,这就需要用到名字改编(name mangling),又叫名字修饰(name decoration)。

名字改编也罢,但由于历史原因,C++没有这方面的标准(C++没有ABI方面的标准,名字改编只是ABI问题的一部分)。于是编译器们各自为政,生成的文件无法通用。

于是:在Windows下,你会发现,同一版本的QtCore4.dll,不同编译器编译出来的无法通用。同一个函数void f(std::wstring s),同一个编译器(MSVC),不同选项(/Zc:wchar_t-/Zc:wchar_t),导出的符号不同。

在Qt中,我们只关注下面两种名字改编:

  • Itanium C++ ABI (GCC3、GCC4,包括MinGW)
  • Microsoft C++ ABI

注:对于Intel编译器,在Windows下和微软ABI一致,在其他平台下和GCC保持一致。

用例子来说话

找个什么例子呢?额... 不妨找个简单的动态库,看看它导出的函数名字吧。Qt的Core和Gui模块都太复杂了,就拿Qt的Test模块来看看吧,QtTest4.dll 或 libQtTest.so.4.8.0

如何看到符号呢?

  • 在windows下,我们可以使用 dumpbin 工具:
dumpbin /EXPORTS qttest4.dll
  • 在linux,我们可以使用 nm 或 readelf 工具:
nm -D libQtTest.so.4.8.0
readelf -Ws libQtTest.so.4.8.0

准备工作完毕,你运行上述命令,即可看到大量的符号出现在屏幕上,我们下面对比Qt Manual给出的函数,看看这些符号(只简单看几个,不然我也看不懂)

放一行太长了,只好这样了,原型/Itanium/Microsoft

1

void QTest::qSleep(int ms)

原型

_ZN5QTest6qSleepEi

Itanium ABI

?qSleep@QTest@@YAXH@Z

Microsoft ABI

2

const char * QTest::currentTestFunction()

 

_ZN5QTest19currentTestFunctionEv

 

?currentTestFunction@QTest@@YAPBDXZ

 

3

int QTest::qExec(QObject *testObject, int argc=0, char **argv=0)

 

_ZN5QTest5qExecEP7QObjectiPPc

 

?qExec@QTest@@YAHPAVQObject@@HPAPAD@Z

 

4

int QTest::qExec(QObject *testObject, const QStringList &arguments)

 

_ZN5QTest5qExecEP7QObjectRK11QStringList

 

?qExec@QTest@@YAHPAVQObject@@ABVQStringList@@@Z

 

5

QTestData & QTest::newRow(const char * dataTag)

 

_ZN5QTest6newRowEPKc

 

?newRow@QTest@@YAAAVQTestData@@PBD@Z

 

6

...

 

...

 

...

 

这堆东西,乱七八糟的,怎么看啊??

试着读读看

void QTest::qSleep(int ms)

原型

_ZN5QTest6qSleepEi

Itanium ABI

?qSleep@QTest@@YAXH@Z

Microsoft ABI

Itanium

_ZN5QTest6qSleepEi

加几个空格

_Z N 5 QTest 6 qSleep E i

_Z

 

C++名字前缀

N...E

复合名字起始字符 QTest::qSleep

 
 

5 QTest

长度为5的名字QTest

 

6 qSleep

长度为6的名字qSleep

i

 

参数类型 int

Microsoft

?qSleep@QTest@@YAXH@Z

这个信息有些多,有些乱,比前面的风格差远了。而且很多过时的东西都混在其中。

C++名字前缀

qSleep

最内层的名字

@

名字分隔符

QTest

前一个名字的外层名字

@@

名字结束

Y

函数调用是 near 方式

A

调用惯例__cdecl

X

返回值类型 void

H

参数类型 int

@

参数表结束

Z

表示这是一个函数

关于这些东西的解释,详见calling_conventions

参考

http://blog.csdn.net/dbzhang800/article/details/6707051

最新文章

  1. 无废话ExtJs 入门教程十七[列表:GridPanel]
  2. kafka 订单应用需求
  3. .NET Actor Model Implementations Differ in Approach
  4. IOS 杂笔-10(Base64 加密)
  5. 一小时学会Markdown写作
  6. python实现微信打飞机游戏
  7. 深入理解Redis:底层数据结构
  8. JQUERY 动态时钟
  9. 深入详解SQL中的Null
  10. Android4.0设置界面改动总结(三)
  11. 反编译app方法
  12. 巧用第三方高速开发Android App 热门第三方SDK及框架
  13. tensorflow机器学习模型的跨平台上线
  14. Building QGIS from source - step by step(随笔3)
  15. IdentityServer4 中文文档 -16- (快速入门)使用 EntityFramework Core 存储配置数据
  16. Ext.util.Format.date与Ext.Date.format区别, 转换时间戳
  17. 微信编辑器 wxEditor 最牛逼的富文本编辑器
  18. [LeetCode] 114. Flatten Binary Tree to Linked List_Medium tag: DFS
  19. 七大排序的个人总结(二) 归并排序(Merge
  20. 奔跑吧DKY——团队Scrum冲刺阶段-Day 6

热门文章

  1. SGU 200 Cracking RSA (高斯消元)
  2. AT&T汇编试讲--获取CPU Vendor ID
  3. python 命令行参数,以及文件操作
  4. ios即时通讯客户端开发之-mac上基于XMPP的聊天客户端开发环境搭建
  5. iframe跨域通信方案
  6. Jquery dom搜索之siblings()方法
  7. C/C++存储区划分
  8. 5.6.3 String类型
  9. 弹出窗口内嵌iframe 框口自适应
  10. Mongodb PHP开发类库