Qtのクロスプラットフォームの共通問題とその解決策

最近では、クロスプラットフォームのプロジェクトのニーズ、プロジェクト自体はUbuntuので書かれているが、執筆時点でも、クロスプラットフォームではないと考えている私は本当にクロスプラットフォームのプロジェクトに従事する初めてと相まって、行っていませんいくつかの迂回路は、私は助けを他の人に期待して、記録について何かを学びました。

 

1. [ツール]

我々はすべて知っているように、Qtのクロスプラットフォーム自体は、理論的には、同じコードは一度だけコンパイルする必要があり、異なるプラットフォームで異なるシステム上で実行することができています。クロスプラットフォームは、単純なようではありません、もちろん、誰難しいことではないでしょう、そうでない人には難しいが、彼らは、関連する知識を持ってしかし、実際には、Qtのクロスプラットフォームは難しい問題ではありません。

いわゆるクロスプラットフォームは、一般的にWindowsとLinux、私の議論の他のOSのうちを指します。

 

まず、選択肢のQtのバージョンを説明します。Qtのバージョンに加えて、オペレーティングシステムから、LinuxとQtはウィンドウのポイントを持っています。

Linuxでの後、Qtの適切なインストールパッケージには、我々はQtのコンパイル時間を使用するときに、実際のLinuxを使用する++ gccとgであるC ++コンパイラが付属しています、そして時にはQtがインストールされコンパイルされない、任意のコンパイラが含まれていません彼らはプロジェクトをビルドすることはできませんので、我々は、コンパイラをインストールしていないからです。

例えば、私たちはQtの上のUbuntuをインストールし、gccのG ++をインストールする必要があり、その後、Qtのを(逆の順序でよい)をインストールします:

sudo apt-get install build-essential libgl1-mesa-dev 
chmod +x qt-opensource-linux-x64-5.7.0.run 
sudo ./qt-opensource-linux-x64-5.7.0.run

Windowsでは、コンパイラを見て、Qtは2種類に分かれています。

一つは、このバージョンでは、MinGWのバージョンではありません、コンパイル時、内蔵のインストールパッケージのQt MinGWのコンパイラを使用して、その追加のQtのインストールが提供された後、直接使用することができます。

他にはMSVCのバージョン、Linuxと同様のこのバージョンでは、コンパイラを提供していますが、ここで使用されるサードパーティのコンパイラを使用すると、VSコンパイラである、あなたは、このバージョンを選択するような場合は、対応をインストールする必要がありません。 VS、例えばvs2015、vs2017等、インストールVS後、QtのMSVC QtCreatorバージョンが相関コンパイラを検出することができ、コードをコンパイルします。最も一般的なバグ・デバッガやその他の問題として、あなたがセットに所有することができ、成功していない場合はもちろん、彼らはその後、ネットワーク上のクエリを解決するため、問題が発生しました。

 

だから、Qtはなぜそんなに無料提供、なぜ世界征服、私たちにそれを使用するキーをだますための方法を提供しませんか?これが理由です。

LinuxでのC ++プログラミング、GCCとG ++コンパイラ必然的に使用している場合:それは私たちが何年も、他のプログラミング・ソリューションを持っています、また、例えば、固定具の使用または通信の多くを作成する前に時間Qtは、後半に登場しましたこれは、最初の選択肢であり、多くのサードパーティのライブラリは、動的ライブラリのためのVSのツールを使用してコンパイルされています。Qtの場合にのみ、独自のコンパイラ(MinGWのコンパイラ)へのこのリードは、ネットワーク上の、その後の多くのサードパーティのライブラリはQtはいくつかのライブラリを整理してコンパイルしないので、Qtの中で使用できなくなります。

我々は、すべての動的ライブラリを使用するようにコンパイラが使用する同じコンパイラでコンパイルする必要があり、桁数、すなわち、同じでなければならないことを知っている:mingwのは、コンパイル済みのDLLを使用し、その逆はできません対、32あなたは、64ビットのダイナミックライブラリをリンクする、というようにすることはできません。(私はここでそれらを繰り返す、その他の情報を確認してくださいませんかわかりません)

そのため、インターネット上のリソースの広い範囲を使用するためには、異なるプラットフォーム、異なるビット数、異なるコンパイラのための多くのバージョンを提供しなければなりません。

 

このことを知って、私たちは自分のQtのバージョンを選択することができるようになります。Linuxでは、選択するためには何もありませんでした、とのMinGW版も利用可能であるように、Windowsで、あなたは、唯一のQtライブラリを所有している場合がありますが、サードパーティ製のライブラリを使用したい場合は、それも考慮MSVCのバージョン、およびVSのバージョンを使用することをお勧めしますそのいずれかを使用します。

2、漢字の問題

(注:このセクションでは、主としてコンテンツ復刻意図されるhttps://blog.csdn.net/e5max/article/details/80908620、から部分的に作成者によって追加されました)

まず、問題は何ですか?

Qtのプログラミングを学習するプロセスでは、ほとんどの人は中国人が文字化けの問題に遭遇しました。三つのカテゴリーにまとめるには:

1は、漢字表示は、QtのCreatorで文字化けになり、トップのエディタがあり、「できませんでしたデコード」... UTF-8「-encoding。編集はできません。」エラー「と」。この時点では、文字化けした文書を編集することはできません。以下に示すように、「ハロー!中国」5つの漢字は文字化けになります:

2、中国語の文字は、通常のQt Creatorで表示されますが、と誤報一連の「一定の改行がある」と、コンパイラが表示されます。実際には、これは文字エンコーディングの問題があります。下図のように:

3、编译时未报错,但生成的程序中文乱码。如下图所示:

其中,第3条是网上提问的最多的,几乎是所有使用MSVC的初学者都会碰到的问题。很多回答是针对Qt4版本的,Qt5中不可用。

二、为什么会出现这些问题?

在解决问题之前,字符编码知识是必需的。你要知道ASCII、GB2312、GBK、Unicode、UTF-8、UTF-16、BOM是怎么回事。此外,你还要明白源码字符集、执行字符集是什么。详细内容可以在网上搜索一下,俯拾即是。


首先,请查询了解上面提到的诸多字符编码名词。然后查看下面我要说明的三块知识点:

1、字符在Qt中显示和处理流程示意图:

Qt字符处理示意图

在上图中,S表示我们的代码文件的编码格式,E代表我们编辑器(这里就是QtCreator)的编码格式,C表示编译器使用的编码格式。

如果S和E一致,那么代码的显示就是正常的。但是要注意,如上图所示,显示和编译用的是不同的编码格式也就是说,Qt中代码显示正确并不代表编译器也能正确识别源文件。

如果S和C一致,那么编译器就能正确识别源代码,此时编译就不会报编码相关的错误。

但即使S和C一致,编译也成功了,但最终显示在界面上的汉字却有可能显示为乱码,这又是为什么呢?

2、执行字符集问题

当编译器识别源代码中的字符串无语法错误后(注意,仅是无语法错误,不代表识别正确),在编译时,它会将识别出来的字符串进行一个转码(如上图红色箭头所示),转码为执行字符集然后写入到我们最终生成的exe可执行文件中,因此,在运行程序时,实际使用的字符信息是经过转码得来的。

3、QString

QString这个类在Qt中表示字符串,是非常基本的类,然而基本却不代表不重要,也不代表它很简单。

QString在内部是使用UTF8来表示字符串的,这一点是不能更改的。

那么当我们需要将其他格式的字符信息在QString表示,该怎么做呢?答案是使用QString类中的fromXXX函数,如fromUTF8就表示以UTF8的格式解析传入的参数,然后将解析出来的字符转码为QString使用的格式,也就是UTF8。fromLatln1则表示以Latln1的格式解码传入的参数,然后转码为UTF8。

而在构造函数一个QString时,在底层默认调用QString::fromUTF8()。

我们也可以使用QString中的toXXX函数来完成UTF8到其他格式的转码。

 

有了上面2和3的知识,我们继续分析上面图片黄色方框中的部分。

红色箭头中,编译器会将识别到的字符串进行一次转码,转为相应的执行字符集,转码后的信息保存在最终生产的可执行程序中。当我们执行这个可执行程序的时候,当执行到该字符串相关的代码部分时,我们会使用它来构建生产QString对象,而由于我们在代码中可以指定QString构造时解析所使用的编码格式(即使用不同的fromXXX函数来构造QString),因此当指定的方式合适时,自然就可以正确显示中文字符。

 

而当我们对形如“xxx”的字符串使用QStringLitura宏时,情况又不一样了,此时黄色方框中的内容不存在。这是为什么呢?

我们在上述描述中可以知道,QString对象的构建是在运行时(at runtime),但当我们使用QStringLitura这个宏时,在编译期间,就会使用“xxx”所提供的字符信息直接生产QString内部数据,这样当程序运行时,就可以避免与QString相关的内存分配,拷贝,转码等一系列消耗,直接使用已生成的QString内部数据,这样可以提高程序的运行效率。

因此,此时黄色方框中的步骤就不存在了,此时,只要编译器可以正确识别源码,就可以正常显示字符。

 

以上就是所有内容,下面我们结合实际的例子,说明以上机制的运行方式,作为理解的参考。


 

1、Qt Creator 的编辑器默认使用UTF-8(代码页65001)编码来读取文本文件。而Visual Studio保存文件时默认采用的是本地编码,对于简体中文的 Windows操作系统,这个编码就是GB2312(代码页936)。如果使用Qt Creator读取由Visual Studio创建的文件,那么编 辑器就会以UTF-8编码格式读取GB2312编码格式的文件,出现中文乱码,因为这两套编码系统对汉字编码是不同的。至于英文部分不会乱码,是因为 UTF-8和GB2312在单字节字符部分是兼容的。


此时,S为GB2312,而E为UTF8,所以会使用UTF8去解码GB2312的文本,表现为:QtCreator中,中文字符乱码。


 

2、MSVC 在编译时,会根据源代码文件有无BOM来定义源码字符集。如果有BOM,则按BOM解释识别编码;如果没有,则使用本地字符集,对于简体中文的 Windows操作系统就是GB2312。那么,当MSVC遇到一个没有BOM的UTF-8编码的文件时,它通常会把文件看作GB2312的来处理。如果 文件全是英文没有问题,但如果包含中文,编译器就会出现误读。这种情况下,Qt Creator编辑器是正常的。但对于MSVC编译器,原代码会被它认识 成下图这个样子:

这是我用EverEdit指定本地编码重读后的结果,可以看到汉字出错,末端的引号也没了。

在 UTF-8中,一个中文字符(汉字或标点符号)占用3个字节,“你好中文!”这5个中文字符共占用15个字节;而在GB2312中,一个中文字符(汉字或 标点符号)占用2个字节,这时,MSVC把UTF-8编码的15个字节加上后面1个字节的英文引号合成16个字节当作8个中文字符处理。之后,MSVC在 这一行里直到末尾换行符出现都没有找到下一个引号,它以为你把字符串在这里敲回车换行了,于是报警称“常量中有换行符”,并引出一系列的错误。

不过,当以无BOM的UTF-8编码的字符串正好凑够偶数个字节时(比如偶数个汉字,或奇数个汉字加奇数个英文字母),编译器通常不会报警,因为它以为用GB2312编码读出的是正确的。


根据上面的描述:

1、当有BOM时,S为UTF8-BOM,E为UTF8,C为UTF8,此时,S和E相同,编辑器显示正常,S和C相同,编译器识别源码正确。

2、当无BOM时,S为UTF8,E为UTF8,C为GB2312,此时,S和E相同,编辑器显示正常,但S和C不同,因此在识别汉字部分时,就会编译报错,而报错的理由,上面描述非常详细,不再赘述。


 

3、不 管源文件是何种编码,只要MSVC能够正确识别,就可以通过编译。但MSVC的执行字符集默认是本地字符集。对我们来说,它生成的可执行文件中的文字是 GB2312编码的。而生成的Qt程序以UTF-8编码来识别GB2312编码的文字,对于“你好中文!”这几个字符,采用GB2312编码后再以 UFT-8编码来读取,就会变成如下的乱码:

当以无BOM的UTF-8编码的字符串正好凑够偶数个字节时(比如偶数个汉字,或奇数个汉字加奇数个英文字母),反而不会出现乱码。那是因为,编译器用GB2312编码读出的乱码本身就是UTF-8编码的,现在又用UTF-8解读,自然就正确了。这纯粹是歪打正着。


根据上面的描述:

1、当有BOM时,S为UTF8-BOM,E为UTF8,C为UTF8,此时,S和E相同,编辑器显示正常,S和C相同,编译器识别源码正确。 然后,MSVC编译器会将识别到对的字符转码为执行字符集,即GB2312,然后使用在代码中使用了fromUTF8来构造QString,即用UTF8解码GB2312字符,因此造成乱码。

2、当无BOM时,S为UTF8,E为UTF8,C为GB2312,此时,S和E相同,编辑器显示正常,但S和C不同,因此在识别汉字部分时,就会编译报错,但当汉字恰好为偶数时,编译器并不会报语法错误,此时识别出来的字符串是乱码(用GB2312解码UTF8),然后将该乱码转码为执行字符集,即GB2312(因为C使用的就是GB2312,因此这里实际上没有发生任何动作),然后使用在代码中使用了fromUTF8来构造QString,恰好歪打正着,显示反而正确了。


 

三、怎么解决这些问题?

首先,你要确定采用哪种源码字符集。你有两个选择:

  1. 采用本地编码字符集(不推荐,跨平台时会比较麻烦,但在Visual Studio环境下配合Add-in工具编程比较方便);

  2. 采用UTF-8编码字符集(推荐,适合跨平台)。

1 “采用本地编码字符集”方案,解决方法如下:

首先,要把项目中所有的头文件和源文件全都转换成GB2312编码保存。

  1. 第1个问题:在Qt Creator中打开项目,点击左侧工具栏“项目”,在“编辑器”选项卡中把“默认编码”改成“GB2312”。如下图所示:

话说回来,既然选择本地字符集,大致上是放弃跨平台了。与其用轻量级的Qt Creator,不如用Visual Studio作开发环境更好。

  1. 第2个问题:“常量中有换行符”等一系列报警已不存在了。

  2. 第3个问题:在字符串常量上加QStringLiteral宏或QString::fromLocal8Bit函数,如:

QString str = "你好中文!";

改为:

 QString str = QStringLiteral("你好中文!");

或者:

QString str = QString::fromLocal8Bit("你好中文!");

不过,在这两种形式下,你都无法用tr方法来创建翻译了。


根据上面的描述:

此时,S、E、C都是GB2312,第一个和第二个问题都解决了,第三个则是因为在实际代码中使用的是fromUTF8构造QString,即用UTF8解码GB2312字符串,因此乱码。

此时,将fromUTF8改为fromLocal8Bit,即用本地字符集,也就是GB2312来解码GB2312,因此显示正确。

QStringLiteral已在上面解释。

这里说不能使用tr,是因为QStringLiteral它是在编译期间就决定了QString的内容,而tr可以进行翻译,是因为它在运行时,根据设置的翻译文件(如英文对应到中文的文件,里面包含了英文字符串到汉字字符串的映射),返回对应的字符串。


 

2 “采用UTF-8编码字符集”方案,解决方法如下:

首先,要把项目中所有的头文件和源文件全都转换成UTF-8+BOM编码保存。

  1. 第1个问题不存在了。

  2. 第2个问题也不存在了。

  3. 第3个问题,你也可以用上个方案中的方法来解决,但有更好的方法。那就是要用到中文字符的头文件和源文件开头加上MSVC的一个宏:

#if _MSC_VER >= 1600
​
#pragma execution_character_set("utf-8")
​
#endif

这个宏告诉MSVC,执行字符集是UTF-8编码的,别瞎整成GB2312的!还有个好处,就是能用tr包中文,方便日后的翻译。最终效果如下:


此时,当有BOM时,S为UTF8-BOM,E为UTF8,C为UTF8,此时,S和E相同,编辑器显示正常,S和C相同,编译器识别源码正确。

如果不适用上面的宏,MSVC编译器会将识别到对的字符转码为执行字符集,即GB2312,然后使用在代码中使用了fromUTF8来构造QString,即用UTF8解码GB2312字符,因此造成乱码。

使用了上面的宏,MSVC编译器会将识别到对的字符转码为执行字符集,即UTF8,然后使用在代码中使用了fromUTF8来构造QString,即用UTF8解码UTF8字符,因此显示正确。


3、中文字符续

除了第二部分遇到的问题外,在设置QSS时也遇到了中文字符问题。

在我的项目中,QSS是作为独立文件存在的,然后在程序运行时,加载进来设置样式,此时如果文件中有中文,可能也会有问题,此时最好的做法就是将QSS中的中文删除。

 

4、第三方库的使用

在项目开发中,使用第三方库必不可少。而当涉及到跨平台时,选取库时一定要提前做好功课,以免后续追悔莫及。

如果不考虑清楚,使用了一个本身就不能跨平台的库,那么后期如果真的需要跨平台了,就需要花很大的精力重新修改代码,而且可能会引入新的bug的问题。

因此,在使用第三方库时,一定要在两个平台上,各自建立一个项目,来测试它的功能,可使用性等。

  • 必须保证可以在两个平台下编译成功第三方库,如果在某个平台下不能编译成功,最好弃用

  • 先创建一个额外的工程,首先单独对这个工程做跨平台,看是否能成功

  • 在各自平台下测试第三方库的功能和性能

 

在做到上述步骤,慎重考虑之后,再去决定是否选用该库。千万不要抱着先干了再说的想法,方法不当,会给自己带来很多工作上的麻烦,甚至无法完成任务。

 

H&A
发布了7 篇原创文章 · 获赞 4 · 访问量 835

おすすめ

転載: blog.csdn.net/qq_34305316/article/details/97136576