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

  1. Windows 系统字符集是 CP936, 即 GBK

  2. Linux 系统字符集是 UTF-8

  3. Windos 下, MSVC 的 binary 默认字符集是 GBK

  4. Linux 下, GCC 的 binary 默认字符集是 UTF-8

  5. UTF16_ANSI 就是将 UTF 16 转换成本地字符集. 这里本地字符集是 UTF-8(Linux), GBK( Windows ).

  6. ANSI_UTF16 是将本地字符集转换为 UTF16. 本地字符集的定义同上. 这里 UTF16_ANSI 和 ANSI _UTF 16 是我们自己编写的一个跨平台的函数. 在 Linux 下, ANSI效果等同于 UTF -8.

  7. 以上是我们编写跨平台且处理中文时关于字符集编码的约定.

  8. 基于以上的约定的动态库的 API 中, char * 和 std::string 的字符集都是本地字符集.

但是: 我们有少量项目使用 Qt. 当编译 Qt 项目的时候, 情况会有所不同.

  1. 在 Qt 环境下, 尽量用 QString. QString 的内部存储是 UTF -16.

  2. 但是 QString 不可避免的要和 多字节编码(UTF-8, GBK均属于多字节编码) 打交道,因此需要注意 QString 的字符集相关的用法

  3. QString::toStdString 返回的 std::string 其编码一定是 UTF-8 的,无论是 Windows 和 Linux 下. 这是 Qt 5, Qt 6 的强制约定.

  4. QString::fromStdString 总是认为输入的 std::string 是 UTF-8 编码,而不管它内容实际上是什么编码. 因此,如果在 Windows 下, std::string("中文") 用QString::fromStdString 转换后会是乱码, 而在 Linux 下正常. 因为 Windows 下, std::string("中文") 是以 GBK 保存的, 强行当作 UTF-8 解析必然乱码.

  5. 为了避免 第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 下的行为一致.

  6. 第 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.

  7. 类似的情况也出现在对 std:: 的各种函数的调用,例如 std::fstream 中的文件名, 它们是以动态库的方式提供,故文件名依然是本地编码. 这时也需要用 用 QString::toLocal8Bit().constData() 而非 QString::toStdString()

  8. 第14~16 是我们编写 Qt 跨平台代码时,关于字符集的约定.

相关推荐
凡人叶枫3 小时前
Effective C++ 条款30:透彻了解 inlining 的里里外外
linux·开发语言·c++·嵌入式开发·effective c++
noipp3 小时前
推荐题目:洛谷 P10907 [蓝桥杯 2024 国 B] 蚂蚁开会
c语言·c++·算法·编程·洛谷
学逆向的4 小时前
C++纯虚函数
开发语言·c++·网络安全
郭泽斌之心4 小时前
MQL5 EA 怎么和外部程序通信?文件三件套协议:参数热更新不重启、状态心跳、远程触发
人工智能·经验分享·深度学习·ea·fay数字人·easydeal
凡人叶枫5 小时前
Effective C++ 条款22:将成员变量声明为 private
linux·开发语言·c++
fofantasy6 小时前
MCM06050H05K00高刚性重载模组选型指南
经验分享·规格说明书
坚果派·白晓明6 小时前
【鸿蒙PC】SDL3 移植:AtomCode Skills 4 步速通多媒体库适配
c++·华为·ai编程·harmonyos·atomcode·c/c++三方库
BomanGe16 小时前
NSK重载高刚性滚珠丝杠技术详解
经验分享·算法·规格说明书
fofantasy7 小时前
NSK LH12AN 微型导轨技术手册
运维·网络·数据库·经验分享·规格说明书
赴生-7 小时前
C++进阶 C++11(下)
开发语言·c++