第02天 了解跨平台开发

1.代码的可移植性

在使用C++进行开发时,经常碰到需要进行跨平台开发的情况。希望在一种操作系统平台(如Windows)开发完的代码不需要任何修改或者仅需要极少量的修改,就能在其他操作系统平台(如Linux)成功编译并能正常运行,这就要求代码具有可移植性。代码具有可移植性,也可以说代码具备跨平台能力,这意味着代码用到的第三方库或软件也应具备可移植性。如果代码具备可移植性,说明代码在不同的操作系统或运行环境下应该表现出相同的行为,这就要处理不同操作系统、不同编译器甚至不同的第三方库之间的差异。那么代码的可移植性具体涉及哪些技术问题呢?

(1)不同操作系统之间数据类型的差异。不同的操作系统之间对C++的基本数据类型的定义有所不同。比如,同样是long类型,在32位操作系统中可能是4字节整数,但是在64位操作系统中可能是8字节整数。

(2)编译器的差异。比如,MSVC(Microsoft Visual C++)的C++编译器有自定义的保留字(关键字)、编译标志等,GCC编译器也有自定义的保留字、编译标志,这两种编译器的保留字、编译标志等可能存在差异。

(3)命令的差异。比如,同样是列出当前目录下的文件列表,在Windows系统中的命令为dir,而在Linux系统中是ls(也可以用dir)。

(4)文件名大小写敏感的差异。Windows系统对于文件名或目录名的大小写不敏感,如aaa.txt和AAA.TXT是同一个文件;而Linux系统是大小写敏感的,aaa.txt和AAA.TXT是两个文件。所以,为了支持跨平台,源代码文件最好使用小写的文件名。除此之外,与目录相关的内容还有目录分隔符,在Windows系统中使用“\”作为目录分隔符,而在Linux系统中使用“/”作为目录分隔符。比如,在Windows中描述一个文件,会写成“c:\temp\a.txt”,而在Linux系统中,则会写成“/usr/local/a.txt”。

(5)操作系统API接口或第三方库的差异。在Windows系统中实现某个功能调用的API接口或第三方库接口与Linux中很有可能不同。

(6)第三方软件的差异。在Windows系统与Linux系统中,可能需要借助不同的软件来实现同一个功能。

当进行C++跨平台软件开发时,软件开发者不可能也没有必要自己实现所有的功能或者处理所有的问题,这就需要选择一些稳定的、可移植的第三方库,这些库为开发者屏蔽了不同操作系统之间的差异,暴露给开发者的是相同的类或接口。在这些第三方库中,Qt是不错的选择。

2.Qt是什么

Qt是一款跨平台的C++图形用户界面应用程序开发框架。开发者既可以用Qt开发GUI(Graphical User Interface,图形用户接口)程序,也可以用它开发控制台工具和服务器等不带界面的程序。Qt最初是由奇趣科技开发的,并且于1995年推出了第一个商业版本。Qt实现了“一次编写、随处编译”,允许开发人员使用同一套代码在不同的平台上成功编译,这些平台包括从Windows到Mac OS X、Linux、Solaris、HP-UX等基于X11的UNIX,Qt甚至可以用在嵌入式Linux和Android中。Qt提供了Designer(设计师)来绘制界面并将其保存为以ui为后缀的界面资源文件,然后通过uic命令将界面资源文件编译为C++代码,这样就实现了所见即所得的界面效果。Qt还提供了强大的文档帮助系统,开发人员可以通过assistant(Qt助手)获得Qt的使用帮助。Qt还提供了QtCreator,这是一个跨平台的IDE(Integrated Development Environment,集成开发环境),可以用来开发、调试基于Qt的程序。使用Qt的QSS(Qt Style Sheets,即Qt样式表)可以开发出非常酷炫的界面程序,Qt还对OpenGL进行了封装,因此可以用来开发3D应用程序。如果要进行C++跨平台开发,Qt绝对是一个非常棒的选择。Qt目前最新版本为6.0(截止到本书出版时)。Qt既有商业协议版本又有开源协议版本,开发者可以根据需要进行选择。

本书的绝大部分案例并未使用Qt类库,仅利用Qt开发环境中的qmake命令将项目的pro文件转换为Visual Studio可以识别的vcxproj后缀的项目文件,以便在Windows中进行项目构建,在Linux上,利用qmake可以生成能被GCC编译器识别的Makefile项目文件。绝大部分案例程序在构建时并不依赖Qt库,在构建成功后启动运行时也不需要Qt库的支持,因此这些案例可以脱离Qt运行环境而独立运行。

既然大部分案例都没有使用Qt类库,那么为什么选择Qt进行开发呢?这是因为Qt的pro项目配置文件可以帮开发人员简化开发环境的配置,如include路径、编译器相关的配置等。这样,在Windows上进行开发时,开发人员无须在Visual Studio中进行配置。而且,使用Qt的pro管理项目的配置文件,还可以实现跨平台的功能,当把程序放在Linux上编译时,就无须专门配置Makefile了,因为利用pro文件就可以生成Makefile,这样一举两得。

3.C++跨平台开发时可选的第三方库

Qt虽然为C++应用程序开发封装了大量的类或者功能,但它无法覆盖C++跨平台开发的全部需求,因为毕竟需求是无限的。开发人员总是希望在某些方面能够有更好用的开发库。这时另外一些支持跨平台的C++库就派上用场了,如下面这些类库。

(1)Protocol Buffers是Google(谷歌公司)开发的一种轻便高效的结构化数据存储格式,可用于结构化数据的序列化,如用作RPC数据交换格式。它可用于通信协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

(2)LibEvent是一个用C语言编写的轻量级的开源、高性能事件通知库。它主要有以下几个亮点:事件驱动,高性能;轻量级,专注于网络,不像ACE那么臃肿庞大;源代码相当精炼、易读;跨平台,支持Windows、Linux、*BSD和Mac OS;支持多种I/O多路复用技术,如epoll、poll、dev/poll、select和kqueue等;支持I/O、定时器和信号等事件;可以注册事件优先级。

(3)POCO C++是一个开源、跨平台的C++类库的集合,它主要提供简单快速的网络通信封装和可移植应用类库。如果开发者正在开发不带界面的服务器程序,开发者可能只希望利用Qt创建和管理项目,而并不希望使用Qt类库,因此就会需要其他的替代库,POCO库就是一个非常不错的选择。

(4)Qt Marketplace是一个在线的Qt扩展市场,目前已经在社区的帮助下推出了第一批优秀扩展。Qt开发者和设计师可在上面共同寻找改善Qt设计、开发的工作流,开发者和公司也可以上传已实现的Qt扩展。这些扩展可以是免费的,也可以是收费的。它对整个Qt生态系统开放。Qt Marketplace项目的负责人希望这个市场成为社区寻找和分享Qt内容的首选之地。根据Qt Marketplace官方发布的信息,第一年发布者将获得所发布产品销售收入的75%,之后几年发布者将获得销售收入的70%。Qt Marketplace与其他市场相比独一无二,因为它让发布者进入了拥有近150万开发者的Qt生态系统。

注意:STL在本书中不作为第三方库。当某个案例开头宣称“本案例不依赖第三方类库”时,表示在该案例中不排除对STL的使用。

4.推荐的开发环境、开发环境的搭建方法

本书所有案例都利用Qt进行开发。这里所说的利用只是利用Qt生成项目文件,绝大部分案例并未使用Qt类库,只有极个别案例依赖Qt类库。本书案例使用的Qt版本为5.12.10。在Windows系统中,本书的教学视频中使用Visual Studio 2019(简称VS 2019)作为IDE开发工具(官方推荐使用VS 2017)。在Linux系统中可以使用Qt Creator 4.11.0作为IDE开发工具,并使用系统自带的GCC编译器进行编译。所有案例均在Windows 10(VS 2019)、RedHat Linux 7.6(GCC 5.5.0)、Qt 5.12.10上构建成功并可正常运行(第7章的串口程序案例仅在Windows验证)。

在继续学习之前,请确保已搭建好开发环境。Windows开发环境的搭建方法请参考配套资源中【附录.pdf】文档中的【附录B】,操作视频请扫描此处二维码观看。

视频讲解

Linux开发环境的搭建方法请参考配套资源中【附录.pdf】文档中的【附录C】,操作视频请扫描此处二维码观看。

视频讲解

5.配套资源(含配套源代码)

本书配套资源包含课件、配套源代码、软件下载地址、开发环境搭建说明、跨平台参考知识等内容,获取方式详见前言。

所有案例均有配套源代码。请先下载本书附带的源代码,阅读本书时请查阅对应源代码进行学习。本书的源代码分为两部分,改动前的代码在src.baseline目录中,各案例以改动前的代码为基础进行修改,改动后的最终代码在src中。如图1-1所示,可以使用WinMerge软件对比案例中改动前后的代码,代码做了哪些改动一目了然。WinMerge的下载地址请见本书配套资源中【资源下载.pdf】文档中的【WinMerge软件】。因篇幅所限,书中部分代码做了省略,请查看配套的完整源代码。

图1-1 用WinMerge软件对比改动前后的代码