什么是跨平台?


举个简单的例子,就是你写的程序在windows下可以运行,在linux下经过简单的处理后也能运行。


标准定义:泛指程序语言、软件或硬件设备可以在多种作业系统或不同硬件架构的电脑上运作。


为什么要关注跨平台?


其实,如果你只希望你的程序在特定的软硬件环境下运行的话,的确可以不用关注和考虑跨平台。但是,这样的程序不具有很好的可移植性,一旦有了在新的环境或者操作系统上运行的需求,则往往需要花费大量的劳力进行修改和移植,甚至整个软件系统都重新设计,这样的代价是很大的、很不划算的。


因此,跨平台是软件开发中一个重要的概念,即希望开发出来的软件,既不依赖于操作系统,也不信赖硬件环境,这样的软件可以得到更加广泛的应用。


那么,是什么阻碍着我们的软件实现跨平台?


MFC应用程序能在linux下跑么? winSocket网络通信程序能运行在Unix下吗? 使用Access数据库记录系统参数的应用程序具备可移植性么? 使用DirectX库开发的多媒体应用能否移植到其他系统呢?


显然,以上各种应用都不具备跨平台的性能,原因如下:


MFC是微软提供的一种应用程序框架,该框架与windows操作系统有着紧密的耦合;winSocket是windows提供的一系列网络编程API,在其他操作系统下有着不同的API接口;Access数据库是基于Windows的桌面关系数据库管理系统,本身不具备跨平台性能,故针对它开发的应用程序才随之丧失了跨平台的特性;而DirectX是一种应用程序接口(也可以说是第三方库),它可以基于windows为平台的游戏或多媒体程序获得更高的执行效率。


由上述例子可以看出,是什么阻碍着我们跨平台?


(1) 非跨平台的应用程序框架     例如:MFC,WinForm

(2) 特定操作系统的API        例如:windows API

(3) 非跨平台的第三方软件      例如:access数据库

(4) 非跨平台的第三方库        例如:DirectX

(5) 程序中出现非跨平台的语句    例如:#prgram once,TRACE,Sleep,CString

    

到此,我们似乎已经找到了跨平台的思路了,对!只要我们能够避免阻碍我们跨平台的因素,我们就能够实现我们软件的跨平台特性,那么,跨平台的道路上,我们有着哪些选择呢?


(1) 应用程序框架


如果我们开发的仅仅是控制台(console)工程,而不需要华丽的或者可视化的界面,那么我们就可以不用选择应用程序框架了;如果我们需要开发可视化的客户端,可以使用跨平台的Qt或者wxWidgets,其中Qt是一个跨平台的C++图形用户界面应用程序框架。它提供给应用程序开发者建立艺术级的图形用户界面所需的各种功能;而wxWidgets也是一个开源的跨平台的C++构架库,提供了GUI(图形用户界面)以及其它工具。


(2) 操作系统API


目前还没有统一的API是不同的操作系统同时都支持的,那么,我们需要使用操作系统的API时,怎么办呢?其实,仔细想想你就能明白,操作系统的API只不过是一系列的函数,提供对文件读写、网络收发、数据库访问、内存管理、进程线程等应用的封装好的方法罢了。其实,我们要实现对应的应用,其实并不一定要使用操作系统提供的API嘛,我们完全可以使用第三方库来实现这些操作功能!例如,强大的boost库就提供了针对上述应用的很全面的操作接口,如 Filesystem模块提供了对文件读写的一系列操作,如 Asio模块提供了对网络通信编程的良好封装,如Thread 模块提供了对创建销毁进程线程的良好实现,Smart Ptr模块提供的智能指针实现了内存的良好管理等等。有了这些第3方库,再加上STL提供的一些容器和算法,还有什么应用我们必须使用操作系统API才能够实现?

    

(3) 第三方软件


其实,第三方软件并不是特别棘手的问题。我们其实很容易找到跨平台的第三方软件替换掉那些不跨平台的软件,虽然偶尔会付出一些小小的代价。像数据库,其实有很多数据库系统都是跨平台的,例如mySQL,PostgresSQL等,我们大可选择这些跨平台的数据库以防止我们的跨平台之路被阻碍。


(4) 第三方库


这个上面已经提到,其实现在存在很多很好的跨平台的第三方库,例如boost库,OpenGL库,rtp应用方面有jrtplib库,网络编程方面有ACE库,等等。对于特定的应用,我相信,你总可以找到一些对应的跨平台的库来满足你的需求。

    

(5) 编程语句


同样,我们需要使用一些跨平台的语句来代替一些非跨平台的语句。例如 #prgram once,我们可以使用下面这样的语句来替换。


    #ifndef XXXX_H_
    #define XXXX_H_
 
    #endif //XXXX_H_

    

当然,对于实在没有什么替换的语句,我们可以使用另外一种方案,那就是条件编译,形式如下:


    #if defined WINDOWS
         Sleep(1000)
    #elif LINUX
         sleep(1000*1000)
    #else

    #endif

    

说到这里,其实,跨平台的基本概念和基本知识我想大家也应该都清楚了。但其实真正想写好跨平台的程序,其实还是任重道远的,因为有很多其他的细节因素需要在实战中慢慢积累,下面我就举几个常见的问题作为本文的结尾吧!

    

1. 文件与目录的大小写以及路径分隔符的差别问题

 

windows下不区分大小写,路径分隔符一般使用"\";linux下区分大小写,路径分隔符使用"/"。在程序中操作文件和目录的路径时这一点要注意。

    

2. linux下和windows下文件扩展名不同


例如,linux下没有exe和dll程序,dll在linux下对应的是.o文件,所以在程序中不要判定系统中是否存在某某exe程序。

    

3. 在每一个.h文件后面都多加上一行,否则在linux下编译时会有警告

    

4. 使用sizeof来确定类型的大小


C++中基本类型的大小(占用的字节数)会随着CPU字长的变化而变化。所以,假如你要表示一个int占用的字节数,千万不要直接写"4",而应该使用sizeof()函数

    

5. 内存对齐


出于CPU处理上的性能考虑,结构体中的数据不是紧挨着的,而是要空开一些间隔。这样的话,结构体中每个数据的地址正好都是某个字长的整数倍。由于C++标准中没有定义内存对齐的细节,因此,你的代码也不能依赖对齐的细节。凡是计算结构体大小的地方,都应该老老实实写上sizeof()。


好了,就说这么多了,希望我在跨平台软件编程方面的心得能够对你有所帮助,有任何其他疑问,欢迎来信交流:lujun_hust@gmail.com,或者关注我的新浪微博 @卢_俊 获取最新的文章和资讯。