跨平台项目中QString 与 非Qt 跨平台动态库在字符集上的一个实用的互操作约定.

1.  Windows 系统字符集是 CP936,  即 GBK
2.  Linux  系统字符集是 UTF-8
3.  Windos 下, MSVC 的 binary 默认字符集是 GBK 
4.  Linux 下, GCC 的 binary 默认字符集是 UTF-8
6.  UTF16_ANSI   就是将 UTF 16 转换成本地字符集.  这里本地字符集是 UTF-8(Linux),  GBK( Windows ).
7.  ANSI_UTF16   是将本地字符集转换为 UTF16. 本地字符集的定义同上.  这里 UTF16_ANSI 和 ANSI _UTF 16 是我们自己编写的一个跨平台的函数.  在 Linux 下, ANSI效果等同于 UTF -8. 
8.  以上是我们编写跨平台且处理中文时关于字符集编码的约定.
9.  基于以上的约定的动态库的 API 中,  char * 和 std::string 的字符集都是本地字符集.

但是:  我们有少量项目使用 Qt. 当编译 Qt 项目的时候, 情况会有所不同. 
10. 在 Qt 环境下, 尽量用 QString.    QString 的内部存储是 UTF -16.
11. 但是 QString 不可避免的要和 多字节编码(UTF-8, GBK均属于多字节编码) 打交道,因此需要注意 QString 的字符集相关的用法
12. QString::toStdString  返回的 std::string 其编码一定是 UTF-8 的,无论是 Windows 和 Linux 下. 这是 Qt 5, Qt 6 的强制约定.
13. QString::fromStdString 总是认为输入的 std::string 是 UTF-8 编码,而不管它内容实际上是什么编码. 因此,如果在 Windows 下,  std::string("中文")  用QString::fromStdString 转换后会是乱码, 而在 Linux 下正常. 因为 Windows 下, std::string("中文") 是以 GBK 保存的, 强行当作 UTF-8 解析必然乱码.
14.  为了避免 第13 的问题, 可以将 MSVC 的编译选项中加上 /utf-8, 这样, MSVC 就会认为 C++ 的源码以及编译出来的 binary 中的字符串都是 UTF-8 的.  于是  std::string("中文")  即使在 windows 下也是以 UTF8 编码存在, 这样就和 linux 一样了. 这会大大简化在cpp 源码中 QString 与 std::string 的互转换的复杂性.  但要注意的是, cpp 源码一定得用 UTF-8 NO BOM 保存. 按照这个原则, QString 与 std::string 的互转在 linux 和 windows 下的行为一致.
15.  第 14 条解决了 Qt 项目中 cpp 内部 QString 和 std::String 的互转问题.  但是要注意的是, 如果 Qt 项目需要与 DLL API 交互, 而这些 DLL 依然遵从第1~9 的约定(通常总是这样), 则 API 中的 char * 依然是本地编码. 这样, 按照第 14条, 在 Windows 下, QString::toStdString().c_str()  得到的 char * 传递给 DLL API  时会导致中文乱码. 因为 这个字符串是 UTF -8 的, 而 DLL API 期待的却是 GBK.  因此在这种情况下, 需要用 QString::toLocal8Bit().constData() 而非 QString::toStdString().  同理, 当接收到 DLL  API  输出的 char *, 需要用 QString::fromLocal8Bit( DLLAPI() )  来将本能地编码的字符串转换为 QString.
16.  类似的情况也出现在对 std:: 的各种函数的调用,例如  std::fstream 中的文件名, 它们是以动态库的方式提供,故文件名依然是本地编码. 这时也需要用 用 QString::toLocal8Bit().constData() 而非 QString::toStdString()
17. 第14~16 是我们编写 Qt 跨平台代码时,关于字符集的约定.
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值