在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

参考

C++ ABI之名字改编(以Qt为例)的更多相关文章

  1. C++ ABI之名字改变,编译器生成符号研究(以Qt为例)

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

  2. 以QT为例谈环境搭建

    以QT为例谈环境搭建 作者:哲思 时间:2022.1.5 邮箱:1464445232@qq.com GitHub:zhe-si (哲思) (github.com) 前言 自从实习结束,好久没写博客了. ...

  3. Qt编程之Qt样例表(QSS)

    For a long time, Qt has allowed you to decorate your GUIs with CSS’ish style sheets. Inspired by the ...

  4. C++的二进制兼容问题(以QT为例)

    二进制不兼容带来的问题(需要重新编译库文件,以前编译的失效): http://my.oschina.net/lieefu/blog/505363?fromerr=f5jn7rct 二进制不兼容的原理: ...

  5. qt 单例程序

    1.http://qt.nokia.com的网站把QtSingleApplication 的源代码qtsingleapplication-2.6_1-opensource.zip 下载下来,然后解压缩 ...

  6. wchar_t是内置还是别名(亲测有效:wchar_t在windows下是16位整数的别名,在linux等平台下是32位整数的别名。MSVC2008开始默认是/Zc:wchar_t)

    接前一篇C++ ABI之名字改编(以Qt为例),继续看看C++名字改编相关的问题. 问题 MSVC 有一对选项/Zc:wchar_t- 与 /Zc:wchar_t控制wchar_t 于是 wchar_ ...

  7. C++中的名字重整技术

    C++ 一直为人诟病之一的原因是他的二进制模块兼容性不好,即ABI(Application Binary Interface)问题.对于同一源代码,不同编译器,甚至同一编译器不同版本都不兼容,其编译出 ...

  8. qt creator源码全方面分析(2-1-1)

    目录 C++的策略/二进制兼容性问题 定义 ABI注意事项 可做与不可做 库程序员的技巧 位标志 使用d指针 故障排除 在没有d指针的情况下将新数据成员添加到类中 添加已重新实现的虚函数 使用新类 向 ...

  9. 自定义的插件如何加载到Qt Designer中(详细)

    要想在Qt Designer中使用自定义控件,必须要使Qt Designer能够知道我们的自定义控件的存在.有两种方法可以把新自定义控件的信息通知给Qt Designer:“升级(promotion) ...

随机推荐

  1. JVM探秘:四种引用、对象的生存与死亡

    本系列笔记主要基于<深入理解Java虚拟机:JVM高级特性与最佳实践 第2版>,是这本书的读书笔记. Java虚拟机的内存区域中,程序计数器.Java栈和本地方法栈是线程私有的,随线程而生 ...

  2. <算法><go实现>左括号补全-双栈法

    输入:1+2)*33-44)*555-666))) 输出:((1+2)*((33-44)*(555-666))) 代码实现及注释: package main import "fmt" ...

  3. MyBatis原理-延迟加载,一级缓存,二级缓存设置

    一.延迟加载 resultMap中的association和collection标签具有延迟加载的功能. 延迟加载的意思是说,在关联查询时,利用延迟加载,先加载主信息.使用关联信息时再去加载关联信息. ...

  4. Linux 学习笔记 5 文件的下载、压缩、解压、初步认识yum

    写在前面 上节我们通过简单的几组命令,已经完全的实现了文件的移动.删除.更名.以及复制,我们最常用的基本玩法,本节将带着大家学习压缩.解压的相关步骤. Linux 学习笔记 4 创建.复制.移动.文件 ...

  5. 「SP122」STEVE - Voracious Steve 解题报告

    SP122 STEVE - Voracious Steve 题意翻译 Problem Steve和他的一个朋友在玩游戏,游戏开始前,盒子里有 n个甜甜圈,两个人轮流从盒子里抓甜甜圈,每次至少抓 1个, ...

  6. Win10系统下应用窗口任务栏居中效果

    实现步骤: 在资源管理器中新建文件夹,一定要保证文件夹内无任何文件 任务栏上鼠标右键,移动到工具栏上,选择新建工具栏 选择新建的空文件夹 空文件夹出现在任务栏后,鼠标可以拖动工具栏前的两条竖线(图片上 ...

  7. spring boot使用拦截器

    1.编写一个拦截器 首先,我们先编写一个拦截器,和spring mvc方式一样.实现HandlerInterceptor类,代码如下 package com.example.demo.intercep ...

  8. html 鼠标指针讲解

    html 鼠标指针 详情可以看https://www.w3school.com.cn/tiy/t.asp?f=csse_cursor 测试代码: <html> <body> & ...

  9. electron-vue 设置cookie

    //设置登录cookie setCookie(name,value){ var Days=30; var exp=new Date(); var date=Math.round(exp.getTime ...

  10. Winform在控件内实现简单画笔功能

    using System.Drawing; using System.Windows.Forms; namespace ZhuoHuiSchoolroom.ZhuoHuiClass { /// < ...