接前一篇C++ ABI之名字改编(以Qt为例),继续看看C++名字改编相关的问题。

问题

  • MSVC 有一对选项/Zc:wchar_t- 与 /Zc:wchar_t控制wchar_t

  • 于是 wchar_t 可以是 unsigned short 或 __wchar_t(称为原生类型?) 的别名

两个东西混用会怎么样?

首先考虑,会混用么?,是杞人忧天么? 由于 Qt 为 MSVC 提供的二进制包采用的前者/Zc:wchar_t-。考虑:

  • 如果你编译自己的Qt程序时,启用了后者,会怎么样?
  • 如果Qt程序同时使用了其他的C++库,而且这个库编译时采用了后者。会怎么样?

当然

  • 我们可以自己启用 /Zc:wchar_t 来编译Qt解决这样的问题。本文不考虑这个情况。

wchar_t

  • Unicode 4.0标准的5.2节提到:

"The width of wchar_t is compiler-specific and can be as small as 8 bits. Consequently, programs that need to be portable across any C or C++ compilershould not use wchar_t for storing Unicode text. The wchar_t type is intended for storing compiler-defined wide characters, which may be Unicode characters in some compilers."

  • C、C++ 标准对这个 wchar_t 不够明确(以至于C++0x、C1x又引入了char16_t/char32_t)
  • 各编译器实现 wchar_t 时,是通过typedef定义一个别名。在windows下是 16位整数的别名,在linux等平台下,是 32 位整数的别名。

msvc

MSVC,一直以来,wchar_t与其内部两个类型相关

  • unsigned short
  • __wchar_t

wchar_t 可以是二者之一的别名,通过 /Zc:wchar_t- 与 /Zc:wchar_t进行设置

在MSVC2008之前,默认是前者,从MSVC2008开始,默认改为了后者。

例子

直观一点,直接用msvc生成一个动态库,然后看看它导出的符号:

  • 源文件dll.cpp
//dll.cpp
#include <string> __declspec(dllexport) wchar_t * func1()
{
return 0;
} __declspec(dllexport) void func2(wchar_t *)
{
} __declspec(dllexport) std::wstring generateString()
{
return std::wstring();
} __declspec(dllexport) void receiveString(std::wstring str)
{
}
  • 分别用两种wchar_t编译上述文件,分别生成out0.dll 和 out1.dll
cl /EHsc /Zc:wchar_t   /LD dll.cpp  /Feout0.dll
cl /EHsc /Zc:wchar_t- /LD dll.cpp /Feout1.dll
  • 而后,用dumpbin查看导出的符号
dumpbin /EXPORTS out0.dll
dumpbin /EXPORTS out1.dll

导出符号

对于原生类型:注意,其中的 _W 代表 wchar_t 即 __wchar_t的类型

 ?func1@@YAPA_WXZ
?func2@@YAXPA_W@Z
?generateString@@YA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@XZ
?receiveString@@YAXV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@Z

对于unsigned short类型:注意其中的 G 代表wchar_t 即 unsigned short的类型

 ?func1@@YAPAGXZ
?func2@@YAXPAG@Z
?generateString@@YA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@XZ
?receiveString@@YAXV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@@Z

两者改编后的名字不同,如果混用的话:肯定就会因为找不到要找的名字,而出现链接错误了。

对Qt的影响

混用两种 wchar_t 时,

凡是使用 std::wstring 或 wchar_t 的函数都会受影响,比如

QString QString::fromStdWString(const std::wstring & str)
std::wstring QString::toStdWString () const
int QString::toWCharArray(wchar_t * array) const
QString QString::fromWCharArray(const wchar_t * string, int size = -1)

如何解决呢?解决办法就是这种情况下不使用这些函数(似乎很不讲理哈,有些难以接受?)。

不过http://developer.qt.nokia.com上看到有人给出一个方案,恩,尽管还是如我们刚次所说,方法是在msvc下不使用这些函数,只是似乎不是太难接受了。

/*! 自定义的QString到std::wstring转换的封装 */
std::wstring qToStdWString(const QString &str)
{
#ifdef _MSC_VER
return std::wstring((const wchar_t *)str.utf16());
#else
return str.toStdWString();
#endif
} /*! 自定义的 std::wstring 到 QString 转换的封装 */
QString stdWToQString(const std::wstring &str)
{
#ifdef _MSC_VER
return QString::fromUtf16((const ushort *)str.c_str());
#else
return QString::fromStdWString(str);
#endif
}

参考

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

----------------------------------------------------------------------

亲测:printf("%d",sizeof(wchar_t));

mingw,VS2005, VS2010下wchar_t都是2个字节(使用默认设置),其中VS2010手动改成wchar_t-后,也是2个字节

但使用QT在linux gcc下测试,wchar_t是4个字节

----------------------------------------------------------------------

解决办法:

    const wchar_t *text = L"FooBar";

    QString s1 = QString::fromUtf16(reinterpret_cast<const ushort*>(text));
QString s2 = QString::fromWCharArray(text); qDebug() << "sizeof(wchar_t) = " << sizeof(wchar_t);
qDebug() << "QString::fromUtf16(reinterpret_cast<const ushort*>(text)) =>" << s1;
qDebug() << "QString::fromWCharArray(text) =>" << s2;

https://forum.qt.io/topic/55869/from-wchar_t-to-qstring-qstring-fromutf16-or-qstring-fromwchararray

----------------------------------------------------------------------

QT编译器里也可设置:

qmake.conf 里面设置了:
QMAKE_CFLAGS = -nologo -Zm200 -Zc:wchar_t-

win32 {
QMAKE_CXXFLAGS -= -Zm200
QMAKE_CXXFLAGS += /Zm400
QMAKE_CXXFLAGS += /Zc:wchar_t
}
也可能不要设置 QMAKE_CXXFLAGS

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

  1. 通过 AppSwitch 禁用 WPF 内置的触摸让 WPF 程序可以处理 Windows 触摸消息

    原文:通过 AppSwitch 禁用 WPF 内置的触摸让 WPF 程序可以处理 Windows 触摸消息 WPF 框架自己实现了一套触摸机制,但同一窗口只能支持一套触摸机制,于是这会禁用系统的触摸消 ...

  2. tomcat内置jdk(tomcat集成jdk)(windows环境)

    tomcat内置jdk,步骤: 1.在一个已经安装了jdk或者jre的机器上,拷贝一个jre到tomcat根目录下. 2.编辑tomcat/bin文件夹下的catalina.bat文件,在文件开头加上 ...

  3. java实现判断一个经纬度坐标是否在一个多边形内(经自己亲测)

    1.在高德地图上绘制的多边形:经纬度逗号分隔格式:上面是用来方便存坐标的对象:下面是方法测试:直接复制代码即可运行 public class Point { private Double x; pri ...

  4. 【亲测】<g++/gcc>CentOS下g++: command not found问题的解决(c++环境安装)

    CentOS下g++: command not found问题的解决 2017年02月27日 18:09:06 阅读数:5174 标签: centosgcc 更多 个人分类: 问题分析   版权声明: ...

  5. 个人亲测,在win10系统下安装多实例mysql8.0详细教程

    由于公司的新项目需要导入sql脚本,需要更高版本的mysql数据库,原来的数据库我也不想删除和升级,因此安装了第二个mysql8的实例,废话不多说,步骤如下: 1.下载mysqlGPL版本,我下载的版 ...

  6. wchar_t内置还是别名?小问题一则(升级公司以前代码遇到的问题)

    问题: 原来的2008工程用2010编译后,运行程序出现无法定位程序输入点 *@basic_string@_WU@*和*@basic_string@G@* 解决: 关闭“语言选项”中“将WChar_t ...

  7. XAF应用开发教程-内置Attribute功能列表

    在 XAF 框架,一些用来生成一个业务应用程序的信息是在Attribute中指定.您可以将属性应用到业务类 (或它的成员) 指定验证规则,指定如何对数据进行显示. 设置关系类等.本主题提供了有关在何处 ...

  8. 与众不同 windows phone (47) - 8.0 其它: 锁屏信息和锁屏背景, 电池状态, 多分辨率, 商店, 内置协议, 快速恢复

    [源码下载] 与众不同 windows phone (47) - 8.0 其它: 锁屏信息和锁屏背景, 电池状态, 多分辨率, 商店, 内置协议, 快速恢复 作者:webabcd 介绍与众不同 win ...

  9. Android 操作手机内置存储卡中的文件

    场景:需要读取指定文件的内容,此文件是手动存储到手机内置存储卡中的,且手机上不存在SD卡. 对于android通过activity提供的openFileOutput和openFileInput可以直接 ...

随机推荐

  1. appledoc:Objective-C注释文档生成工具

    appledoc是帮助Objective-C开发者从特殊格式的源代码注释中生成类似apple资源代码帮助文档的命令行工具. 安装和使用都非常简单: 安装 git clone git://github. ...

  2. Oracle中NVARCHAR2与VARCHAR2的差别

    NVARCHAR2在计算长度时和字符集相关的: 比如数据库是中文字符集时以长度10为例, 1.NVARCHAR2(10)是能够存进去10个汉字的.假设用来存英文也仅仅能存10个字符. 2.而VARCH ...

  3. 关于给javascript对象添加、删除、修改对象的属性

    以下是自己总结的几种方法 利用动态特性 function Person(){}; var person = new Person(); person.name = 'yy'; person.gende ...

  4. .Net之一般处理程序

    1.一般处理程序是什么? 答:一般处理程序是以.ashx结尾的文件,默认命名为Handler1.ashx. 用在Web项目中,也就是我们常说的网站项目. 2.新建一个一般处理程序 1.1 新建一个空网 ...

  5. CTRL+A, CTRL+C, CTRL+V

    (http://leetcode.com/2011/01/ctrla-ctrlc-ctrlv.html) Imagine you have a special keyboard with the fo ...

  6. Lowest Common Ancestor of a Binary Tree, with Parent Pointer

    Given a binary tree, find the lowest common ancestor of two given nodes in tree. Each node contains ...

  7. POJ 1743 Musical Theme(不可重叠最长重复子串)

    题目链接:http://poj.org/problem?id=1743 题意:有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一 ...

  8. Penalty

    Penalty时间限制:1000 ms | 内存限制:65535 KB难度:2描述As is known to us, the penalty is vitally important to comp ...

  9. 自定义jquery手风琴插件

    手风琴效果是项目中使用频率较高的一种效果,原来项目一直都在用easyui的,临近年末,试着自己写了一个 css样式 /* CSS Document */ body { margin: 0 auto; ...

  10. jquery回调函数callback的使用

    回调函数必须是全局函数或者静态函数,不可定义为某个特定的类的成员函数 callback函数在当前动画100%完成之后执行 $("p").hide(1000); alert(&quo ...