跨平台项目中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 跨平台代码时,关于字符集的约定.

相关推荐
h_a_o777oah20 分钟前
状态机+划分型 DP :深度解析K-划分问题下 DP 状态的转移逻辑(洛谷P2679 P2331 附C++代码)
c++·算法·动态规划·acm·状态机dp·划分型dp·滚动数组优化
一个人旅程~21 分钟前
如何避免在使用win安装U盘启动macbook时候出现键盘触摸板卡死的问题
windows·经验分享·macos·电脑
雪度娃娃2 小时前
Asio异步读写——连接的安全回收问题
开发语言·c++·安全·php
不吃土豆的马铃薯2 小时前
Spdlog 进阶:日志基本控制、日志格式控制、异步记录器
linux·服务器·开发语言·前端·c++
searchforAI3 小时前
AI多模态技术:从语音识别到AI结构化笔记是怎么实现的
人工智能·经验分享·笔记·gpt·whisper·语音识别
liulilittle3 小时前
TCP UCP:基于卡尔曼滤波的BBR增强型拥塞控制算法
linux·网络·c++·tcp/ip·算法·c·通讯
咩咦3 小时前
C++学习笔记26:static 静态成员
c++·学习笔记·static·静态成员变量·静态成员·静态成员函数
秋落风声3 小时前
内存池仿Nginx C++实现
c++·nginx
小白要努力sgy3 小时前
实时通信框架CyberRT
c++·自动驾驶·实时通讯
hansang_IR3 小时前
【记录】loj2967「COCI 2010.03.06」PROGRAM
c++·算法