跨平台软件的开发方式

 

 


 跨平台软件的开发方式       版块跳转 新手园地      硬件问题Linux系统管理Linux网络问题Linux环境编程Linux桌面系统国产LinuxBSD      BSD文档中心AIX      AIX文档中心AS400Solaris      Solaris文档中心HP-UX      HP文档中心SCO UNIX      SCO文档中心互操作专区IRIXTru64 UNIXMac OS X门户网站运维集群和高可用服务器应用监控和防护虚拟化技术架构设计行业应用和管理服务器及硬件技术      服务器资源下载云计算      云计算文档中心      云计算业界      云计算资源下载存储备份      存储文档中心      存储业界      存储资源下载      Symantec技术交流区安全技术网络技术      网络技术文档中心C/C++      GUI编程      Functional编程内核源码      内核问题移动开发      移动开发技术资料ShellPerlJava      Java文档中心PHP      php文档中心Python      Python文档中心RubyCPU与编译器嵌入式开发驱动开发Web开发VoIP开发技术MySQL      MySQL文档中心SybaseOraclePostgreSQLDB2Informix数据仓库与数据挖掘NoSQL技术IT业界新闻与评论IT职业生涯      猎头招聘IT图书与评论      CU技术图书大系      Linux书友会二手交易下载共享Linux文档专区IT培训与认证      培训交流      认证培训清茶斋投资理财运动地带快乐数码摄影      摄影器材      摄影比赛专区IT爱车族旅游天下站务交流博客SNS站务交流区CU活动专区      Power活动专区      拍卖交流区  最近访问的版块 

 返回列表 发帖 

阅读  2643   回复  1 分享到: 

xuyeli
发短消息
加为好友
xuyeli 当前离线

UID
16691916
帖子
4
精华
0
积分
11
可用积分
11 
信誉积分
100 
专家积分
0 (本版:)空间积分

阅读权限
10
在线时间
0 小时
注册时间
2003-04-15
最后登录
2004-01-03
 
新手

 

帖子
4
主题
2
精华
0
可用积分
11 
专家积分
0 (本版:0)在线时间
0 小时
注册时间
2003-04-15
最后登录
2004-01-03
状态:...当前离线...

[微博] [博客] [短信]
  [倒序看帖]
1楼 发表于 2003-12-31 20:55 | 只看该作者

--------------------------------------------------------------------------------


原创:smalltalk
随着经济和技术的发展,全球化进程的加速,特别是互联网的发展和普及,为软件提供了一个世界范围的运行环境,当一个软件发布到Internet上面时,这个软件很可能瞬间在全世界就被人使用。从软件开发商的角度来看,同时具有跨平台和全球化特性的软件能够最大限度的占有市场;从自由软件开发团体和个人来看,开发的软件不但能够运行在多种操作系统下,而且还能够以不同的语言版本运行,全世界用户都可以使用,这本身就符合自由和开放的追求。由于这些因素,跨平台技术和全球化技术一直是软件业研究和发展的重要课题。
开发跨平台软件和全球化软件的最大目的是为了争取更多的用户,获得更大的市场。跨平台软件能够在多个不同类型的操作系统下运行,它从操作系统层次拓宽软件的用户群体;全球化软件是既具有国际化特性又进行了本地化处理的软件,这样,世界上不同国家和地区的用户都能以自己熟悉的语言和习惯来使用该软件。具有跨平台特性的全球化软件是非常有“魅力的”,它能够吸引到更多的潜在用户。
由于跨平台和国际化两者都是特别广泛的概念,不同的软件架构、不同的开发语言,采用的方法各不相同,为了做到不以偏概全,本篇文章将主要针对那些采用C/C++语言进行开发的、并准备添加或者已经具有跨平台特性的、同时还需要全球化的软件。文章为开发者在设计和实现这类软件时提供一些指导性意见,给出一些针对跨平台软件实施全球化的方法,并提出了一种采用跨平台资源文件和模块配合的解决方案和具体实现。

*什么是跨平台软件
跨平台软件技术在过去的十几年来逐步发展,特别是当个人计算机(PC & MAC)性能的提高,LINUX操作系统的出现,JAVA语言的推出,呈现出跳跃发展的趋势。目前不但很多著名的自由软件项目提供跨平台的自由软件,而且很多专业的软件厂商也将他们的产品向不同的平台移植。在发展的历程中,跨平台软件技术也逐步形成规范,但由于平台固有的异质性,在进行跨平台软件开发时,往往在软件的功能、效能与移植性等之间,要做适当的权衡,比较难整理出一般性的、与平台及工具种类无关的法则。
什么是跨平台软件,简单讲就是至少可以运行在两个不同操作系统平台下的软件,完成相同或者相似的功能,而且这个软件的可执行程序来自与一份源代码。

*跨平台软件的开发方式
跨平台软件的开发方式大体有三种,第一种是先在一个基准平台上开发好,然后再移植到其他的操作系统;第二种是采用的跨平台模块组合;第三种是采用虚拟机技术,利用平台无关的语言进行开发。

1. 移植
第一种开发方式是比较传统的做法,也是一直被广泛采用的方式。这种做法也称为软件移植(Porting),即把在一种操作系统下运行的软件通过改写部分代码,移植到另外一种或多种操作系统下运行。软件最初的设计、编码以及移植时使用的工具,这些决定了移植的代价。
如果软件在最初的设计、编码时没有考虑到以后的移植,大量采用了平台相关的技术和平台相关框架库进行编码,对这些代码移植将付出极高的代价。一种极端的情况是最初使用的开发语言不能跨平台的,以后要对这个软件进行移植,将不得不更换开发语言重新编写全部代码,还要进行全新的测试,这样的软件在移植时是异常困难的。
1.1. 宏定义
软件的代码,从跨平台的角度来看,可以分为平台相关的和平台无关的。采用C/C++编写的软件,在进行移植时,平台无关的的代码基本上不需要做大的改动,但平台相关的代码需要做很大的调整。这里所说的平台包括操作系统和编译器,为了能够做到让编译器在编译时根据当前的平台状况来自动选择需要编译的代码,我们一般需要用C/C++的编译宏指令来实现。举个例子,下面的一段代码是得到系统当前的时间并且格式化成字符串的操作,注意其中宏指令#ifdef …#else…#endif的使用。这段代码可以在Win32、Linux和大多数Unix平台通过编译:

#include <stdio.h>;
#include <time.h>;

#ifdef WIN32
#define LOCALTIME_R(t)  localtime((t))
#define SNPRINTF _snprintf
#else
#define LOCALTIME_R(t)  localtime_r((t), (struct tm *)&tmres)
#define SNPRINTF snprintf
#endif

char * getcurrentdate(char *buffer, unsigned int buflen)
{
  if (buffer)
  {
    struct tm *tmnow;
    time_t long_time;
    time(&long_time );                     /* Get time as long integer. */
    tmNow = LOCALTIME_R( &long_time );  /* Convert to local time.     */
    SNPRINTF(buffer, buflen, "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
      tmnow ->;tm_year+1900, tmnow ->;tm_mon + 1, tmnow ->;tm_mday,
      tmnow ->;tm_hour, tmnow ->;tm_min, tmnow ->;tm_sec);
  }
  return buffer;
}

研究一下上面的代码我们可以发现,由于一些库函数是非ANSI标准的,平台间有些差异,比如获得格式化字符串的函数在Win32平台叫_snprintf,而在Unix/Linux平台叫snprintf,它们之间的差别不是太大,通过使用编译宏指令就可以区分。
1.2. 编译环境识别
在C/C++编译器编译源码时,为了能够识别当前环境的状况,这包括编译器的类型和版本,操作系统的类型和版本,计算机CPU的类型,机器内部的字节顺序等,每种编译器内部一般规定了一些常用的宏定义,利用这些定义就可以区分出当前的编译环境了。如果我们开发的软件需要在很多不同的平台很编译器上编译,这时候环境就比较复杂了,这个时候如果我们能够将编译环境的宏定义转换成我们自己内部的约定,然后全部使用内部的约定来处理宏,这会简化我们进行跨平台移植的操作。举例来说,下面的一段代码可以区分目前多种常用的编译环境:

#ifndef _ENV_MACROS_H_
#define _ENV_MACROS_H_

/***************************************************************************
*
* _ENV_I386                Intel i386/i486/Pentium (little endian)
* _ENV_ALPHA               Compaq/Digital Alpha (little endian)
* _ENV_SPARC               Sun Sparc
* _ENV_HPPA                HP PA-RISC
* _ENV_MIPS                MIPS
* _ENV_PPC                 PowerPC
* _ENV_POWER               POWER Processors.
*
* _ENV_MSVCPP              Microsoft Visual C++ compiler; version
* _ENV_WIN                 32 or 64 bit Windows
* _ENV_WINNT               Windows NT
* _ENV_WIN32               32 bit Windows
* _ENV_WIN64               64 bit Windows
*
* _ENV_UNIX                UNIX
*
* _ENV_SOLARIS             SUN Solaris
* _ENV_LINUX               Linux
* _ENV_HPUX                HP UNIX
* _ENV_AOSF                Digital UNIX/Tru64 UNIX
*
* _ENV_AIX                 IBM AIX
* _ENV_IRIX                SGI IRIX
* _ENV_OS390               IBM OS/390
* _ENV_AS400               IBM OS/400, AS/400
* _ENV_MACOS               Macintosh
*
* _ENV_GNUC                GNU C/C++ compiler; major version
*
* _ENV_HP_ACC              HP aC++ compiler; version
*
* _ENV_SUNPRO              Sun Pro/Workshop/Forte compiler; version (_ENV_SUNPRO_CC)
* _ENV_SUNPRO_CC           Sun Pro/Workshop/Forte CC compiler; version
* _ENV_SUNPRO_C            Sun Pro/Workshop/Forte C compiler; version
*
* _ENV_SUN_SPARC           Sun Sparc compilation mode
* _ENV_SUN_SPARC32         Sun Sparc 32-bit compilation mode
* _ENV_SUN_SPARC64         Sun Sparc 64-bit compilation mode
* _ENV_SUN_I386            Sun i386 compilation mode
*
* _ENV_AOSF_CC             Compaq C++ compiler for Tru64; version
*
* _ENV_INT64_NATIVE        Compiler provides a 64-bit integer (not supported yet)
* _ENV_64BIT_NATIVE        defined for 64 bit platforms       (not supported yet)
*
* _ENV_CSET                IBM AIX xlC, xlc, etc. this may be in old version.
* _ENV_IBMC                IBM AIX c compiler,xlc, cc.
* _ENV_IBMCPP              IBM AIX cpp compiler, xlC.
* _ENV_MVSCPP              IBM OS390 c++, cxx.
* _ENV_MIPSPRO_CC          SGI IRIX C
*
* _ENV_BIG_ENDIAN_ARCH     Defined if big-endian architecture
* _ENV_LITTLE_ENDIAN_ARCH  Defined if little-endian architecture
*
* _ENV_SYSCALL             __stdcall on Windows
*
* _ENV_DECLSPEC_DLLEXPORT  __declspec(dllexport) for VC++; empty otherwise
* _ENV_DECLSPEC_DLLIMPORT  __declspec(dllimport) for VC++; empty otherwise
*
***************************************************************************/


/*********************************/
/*  Operating system / platform  */
/*********************************/

/* Windows platforms */
#if (defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) || defined(__WIN32__))
#define _ENV_WIN
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
#define _ENV_WIN32
#elif (defined(WIN64) || defined(_WIN64))
#define _ENV_WIN64
#endif
#ifdef _WIN32_WINNT
#define _ENV_WINNT
#endif
/* Alpha OSF / Tru64 / Digital UNIX */
#elif (defined(__osf__))
#define _ENV_AOSF
#define _ENV_UNIX
/* SUN Solaris - assumed */
#elif (defined(__sun))
#define _ENV_SOLARIS
#define _ENV_UNIX
/* IBM AIX */
#elif (defined(_AIX))
#define _ENV_AIX
#define _ENV_UNIX      /* AIX4.2 supports UNIX95, AIX4.3 supports UNIX98 */
/* SGI IRIX */
#elif (defined(IRIX))
#define _ENV_IRIX
#define _ENV_UNIX
/* IBM OS390 */
#elif (defined(__MVS__))
#define _ENV_OS390
#define _ENV_UNIX    /* OS/390 V2R2 UNIX95, OS/390 V2R7 UNIX98 */
#elif (defined(EXM_OS390))
#define _ENV_OS390
#define _ENV_UNIX
/* IBM AS400 */
#elif (defined(__OS400__))
#define _ENV_AS400
#define _ENV_UNIX
/* Macintosh */
#elif (defined(macintosh))
#define _ENV_MACOS
/* Linux */
#elif (defined(__linux__))
#define _ENV_LINUX
#define _ENV_UNIX
/* HP Unix */
#elif (defined(__hpux))
#define _ENV_HPUX
#define _ENV_UNIX
/* Else */
#else
#warning  "Unknown platform!"
#endif


/**************/
/*  Compiler  */
/**************/

#if (defined(_MSC_VER)) /* Microsoft Visual C++ */
#define _ENV_MSVCPP _MSC_VER
#elif defined(__BORLANDC__)
#define _ENV_BORC        /* Borland C/C++ */
#elif defined(__WATCOMC__)
#define _ENV_WATCOMC    /* watcom c/c++ */
#elif (defined(__GNUC__)) /* GNU Project */
#define _ENV_GNUC __GNUC__
#elif (defined(__SUNPRO_CC) || defined(__SUNPRO_C)) /* SUN Pro/Workshop/Forte */
#define _ENV_SUNPRO __SUNPRO_CC
#ifdef __SUNPRO_CC
#define _ENV_SUNPRO_CC __SUNPRO_CC
#endif
#ifdef __SUNPRO_C
#define _ENV_SUNPRO_C __SUNPRO_C
#endif
#elif (defined(__HP_aCC)) /* HP aCC */
#define _ENV_HP_ACC __HP_aCC
#elif (defined(__xlC__))    /* IBM C SET */
#define _ENV_CSET __xlC__
#elif (defined(__IBMC__))   /* IBM c compiler */
#define _ENV_IBMC __IBMC__
#elif (defined(__IBMCPP__)) /* IBM c++ compiler */
#define _ENV_IBMCPP __IBMCPP__
#elif (defined(_ENV_IRIX) || defined(__sgi))
#define _ENV_MPISPRO_CC
#elif (defined(__MVS__) && defined(__cplusplus)) /* OS390 c++ compiler */
#define _ENV_MVSCPP
#elif (defined(EXM_OS390) && defined(__cplusplus)) /* OS390 c++ compiler */
#define _ENV_MVSCPP
#elif (defined(__OS400__))
#elif (defined(__DECCXX_VER)) /* Compaq C++ */
#define _ENV_AOSF_CC __DECCXX_VER
#else
#warning  "Unknown compiler!"
#endif


/****************************/
/*  Processor architecture  */
/****************************/

#if (defined(_ENV_MSVCPP))

#ifdef _M_IX86 /* i386 architecture */
#define _ENV_I386
#endif
#ifdef _M_ALPHA /* Alpha architecture */
#define _ENV_ALPHA
#endif

#elif (defined(_ENV_SUNPRO))

#ifdef __sparc /* Sparc architecture - 32-bit compilation mode */
#define _ENV_SPARC
#define _ENV_SUN_SPARC
#define _ENV_SUN_SPARC32
#endif
#ifdef __sparcv9 /* Sparc architecture - 64-bit compilation mode */
#define _ENV_SPARC
#define _ENV_SUN_SPARC
#define _ENV_SUN_SPARC64
#endif
#ifdef __i386 /* I386 architecture */
#define _ENV_I386
#define _ENV_SUN_I386
#endif

#elif (defined(_ENV_AOSF_CC))

#ifdef __alpha /* Alpha architecture */
#define _ENV_ALPHA
#endif

#elif (defined(_ENV_GNUC))

#if (defined(__alpha) || defined(__alpha__))
#define _ENV_ALPHA
#elif (defined(__i386__))
#define _ENV_I386
#elif (defined(__sparc))
#define _ENV_SUN_SPARC32
#elif (defined(__hppa__))
#define _ENV_HPPA
#elif (defined(__mips__))
#define _ENV_MIPS
#elif (defined(__PPC__))
#define _ENV_PPC
#else
#warning  "Unknown processor architecture!"
#endif

#elif (defined(_ENV_HP_ACC))
#if defined(__hppa)
#define _ENV_HPPA
#endif

#elif (defined(__mips) || defined(__mips__) || defined(__MIPS__))
#define _ENV_MIPS

#elif (defined(_ENV_AIX))
#if defined(_POWER)
#define _ENV_POWER
#endif

#elif (defined(_ENV_MACOS))
#define _ENV_PPC

#elif (defined(_ENV_OS390)||defined(_ENV_AS400))
#define _ENV_POWER

#else
#warning "Unknown processor architecture!"

#endif


/*****************/
/*  Endian-ness  */
/*****************/

#if (defined(_ENV_I386) || defined(_ENV_ALPHA))
#ifndef _ENV_LITTLE_ENDIAN_ARCH
#define _ENV_LITTLE_ENDIAN_ARCH
#endif /* _ENV_LITTLE_ENDIAN_ARCH */
#ifdef _ENV_BIG_ENDIAN_ARCH
#undef _ENV_BIG_ENDIAN_ARCH
#endif /* _ENV_BIG_ENDIAN_ARCH */
#else /* Sparc, etc. */
#ifndef _ENV_BIG_ENDIAN_ARCH
#define _ENV_BIG_ENDIAN_ARCH
#endif /* _ENV_BIG_ENDIAN_ARCH */
#ifdef _ENV_LITTLE_ENDIAN_ARCH
#undef _ENV_LITTLE_ENDIAN_ARCH
#endif /* _ENV_LITTLE_ENDIAN_ARCH */
#endif /* Little-endian architectures */

/* TBD:  How the hell do I detect endian-ness of HPPA machines, or is
   it transparent to the program? */


/**************************/
/*  Miscellaneous macros  */
/**************************/

#if (defined(_ENV_MSVCPP))
#define _ENV_DECLSPEC_DLLEXPORT __declspec(dllexport)
#define _ENV_DECLSPEC_DLLIMPORT __declspec(dllimport)
#define _ENV_SYSCALL            __stdcall

#define _ENV_DECLSPEC_DLLEXPORT_MID

#elif defined(_ENV_OS390)

#define _ENV_DECLSPEC_DLLEXPORT
#define _ENV_DECLSPEC_DLLIMPORT
#define _ENV_SYSCALL          
#define _ENV_DECLSPEC_DLLEXPORT_MID _Export

#else /* not _ENV_MSVCPP */

#define _ENV_DECLSPEC_DLLEXPORT
#define _ENV_DECLSPEC_DLLIMPORT
#define _ENV_SYSCALL

#define _ENV_DECLSPEC_DLLEXPORT_MID

#endif /* _ENV_MSVCPP */

#endif /* _ENV_MACROS_H_ */

以上的代码将原来编译器各自的环境宏转换成统一的以_ENV_开始的宏定义,可以区分当前编译器的类型、操作系统类型、系统内部字节顺序和计算机CPU类型等信息。有了这些信息,可以在移植代码和跨平台编码时方便地使用平台相关的特性。

1.3. 定义通用的数据类型
在目前的大多数计算机系统中,基本的数据类型在字节长度上基本一致,比如int类型占4个字节,char类型占1个字节等,但有些基本的数据类型还是有差别的,比如float、double和64位的整数类型,不同的平台还是有些差别的,为了方便进行跨平台的编程,定义一个通用的数据类型可以简化花费在数据类型上的时间。

1.4. 利用平台交叉工具移植
随着个人计算机性能的提高,目前比较先进的PC处理能力已经不比采用Unix操作系统平台的工作站差,苹果机(Mac)的速度也在成倍增长,最快Power Mac G5系列已经的采用了主频在2GHz以上的RISC 处理器。在这样的情况下,将原来在Unix平台上运行的软件下移到PC和Mac已经成为可能,这可以大大降低该软件的硬件平台的投资;同样,将PC或Mac上软件上移到Unix平台,可以充分发挥Unix平台的处理能力,更加有效地利用Unix平台,这同样也重要意义。在这样的背景下,有一些专业研究跨平台开发技术的公司和社会团体针对特定的应用推出了各种软件移植的解决方案,运用这些工具可以大大减少移植的代价。
1.4.1. 从Unix/Linux到Windows
Cygwin是Cygwin公司(http://cygwin.com/)的产品,它提供了Windows操作系统下的一个UNIX环境,它可以帮助程序开发人员把应用程序从UNIX/Linux移植到Windows平台,是一个功能强大的工具集。 Cygwin由仿真层和一组工具组成,cygwin1.dll:它作为UNIX的一个仿真层,提供UNIX API功能; Cygwin工具负责创建一个UNIX或Linux的外观界面。 Cygwin可以在Windows CE以外,Windows 95以上的所有非beta版本的Windows OS下工作,如Windows 98、Windows 2000、Windows XP等。 在Cygwin提供的仿真环境下,提供经过移植的Gcc编译器,很多原来在Unix/Linux上用Gcc编译的软件可以不加修改地在Windows下编译并运行,这极大地方便了软件从Unix到Window的移植,特别是一些开发原码的项目。

NuTCRACKER是MKS公司(http://mkssoftware.com/)的产品,它为开发人员在Windows下提供了一个Unix的环境,用户可以方便地将Unix/Linux上使用X server、多线程程序移植到Windows平台下运行。
   
MKS Toolkit企业开发版可以不仅可以开发、移植和部署非图形化的Unix应用程序和脚本程序,而且还可以移植原来使用X Windows, OpenGL。
在安装好NuTCRACKER平台后,用户甚至可以直接使用Visual C++集成环境来编译来自Unix/Linux上的代码。直接将Unix上的代码拿到Windows下编译执行,这大大地节省了移植的成本。

1.4.2. 从Windows到Unix/Linux
Wind/U是bristol公司(http://bristol.com/)开发的产品,它提供了一种将Win32程序顺利地移植到Unix和Linux操作系统方法。它在Unix和Linux系统上实现了Win32的API以及MFC框架,而且比较稳定。通过它提供的库和工具,可以十分方便地将Win32上使用API和MFC的软件移植到各种Unix和Linux系统中,大大节省移植的代价,由于它是一种商业产品,品质有保证,目前已经被很多公司采用。下图是Wind/U的系统结构:

目前Wind/U已经可以很方便地支持从Win32到Solaris、HP-UX、AIX和RedHat Linux的移植。

Visual MainWin 是 MainSoft(http://mainsoft.com/)公司的产品,它也提供了从Win32程序代码直接生成Unix/Linux程序的方法。
Visual MainWin 是一个企业级的移植和跨平台开发软件,它可以利用Visual C++集成环境来编写程序,然后将它们部署到多种的Unix平台中,并生成本地执行程序。它由两部分组成,Visual MainWin SDK和Visual MainWin 运行库, SDK是一个安装在Visual Studio中的跨平台插件,这个插件可以配合运行库来生成高可靠性的Unix平台代码。下图是Visual MainWin的使用框图:
最新的Visual MainWin 5甚至可以移植.net框架和MFC7的应用程序到Unix平台。

2. 跨平台模块
采用跨平台模块来组合开发跨平台软件,实际上是采用了组件的思想来进行跨平台软件的开发。这种方法目前正在被广泛采用,特别适用与具有跨平台需求的新产品开发中。在新的软件产品进行设计时就考虑到跨平台的需求,将软件按功能分成多个可组合的模块,定义好需求,然后由多个模块小组独立完成单个模块的,并完成在目标平台上的测试,同时的项目整合小组利用开发好的模块,组合成产品。由于各个模块都是跨平台设计的,所以整合时的跨平台问题会大大减少,这样可以在很短时间内推出一个产品的多个平台的运行版本。
模块的思想非常有利于软件的复用,一般情况下,规模化经营的软件公司的产品大都形成系列化,各软件间的都有功能交叉的部分,采用模块化的思想,将这些部分独立出来,交由专门的小组负责维护和升级,让各产品组有更多的精力放在产品功能的更新上,有利于公司的整体效率的提高。如果一个公司的产品大多是跨平台的产品,那么组成专门的跨平台模块组是非常合适的。
跨平台模块一般的要求也比较复杂,一般都要在三个典型的基准平台是Win32、Linux和Solaris。如果公司的产品还要支持Apple公司的平台,还的加上MacOS。由于平台的多样性,造成了跨平台模块开发的不轻松,但由于模块相对功能比较独立,模块间的耦合度不大,所以跨平台模块的难度还是限制在一定范围的。
目前,不仅大型的专业软件公司转移传统的以产品为团队的模式到以模块为团队的模式,很多自由和共享软件组织也向模块化方向发展。向Apache、GNU、FSF、ICU、ACE等都是比较闻名的开源软件团体,他们都向外界提供成熟的开发源码的跨平台模块。很多商业公司的软件都采用他们的成果来加速软件开发的速度。
跨平台模块虽然在功能上比较独立,但由于众多的平台,在设计和编码时,为了考虑兼容性,弱化了效率上的考虑,当软件整体功能比较关注执行的效率时,就要在模块的兼容性和效率上做出适当的选择。

3. 虚拟机技术
虚拟机技术的典型代表就是Java语言,Java最初由Sun公司提出,是一种跨平台的语言。实际上Java本身并不是一种跨平台语言,而是它采用跨平台的虚拟机来实现源码“一次编译,到处运行”的功能。采用Java开发的语言可以不加修改移植到不同的平台运行,但这局限与JDK提供的现有功能,如果要使用到平台相关的特性,这还是非常不容易的工作。目前,由于Java虚拟机的性能和用户接收程度,在一些关键性的应用场合,还很难看到 Java的身影。由于本篇文章主要关注采用C/C++语言的软件的跨平台和国际化问题,这里对Java及其虚拟机不做更深入的讨论。实际上,除了Java,虚拟机技术是广泛采用的跨平台技术。
以前,很多的游戏都是在任天堂、世嘉、SONY PS/2游戏机上运行的,这些游戏机采用专用的图形处理芯片和声音,能够显示出十分绚烂的色彩和动听的声音,使得游戏非常吸引人。近年来,PC的性能快速提高,于是出现了一种可以支持在PC机上玩游戏机上游戏的模拟器,这种模拟器实际上就是一种典型的虚拟机,它在二进制码级模拟游戏机的功能。
上面提到的Wind/U系统实际上就是在Unix系统上虚拟了Win32的运行环境,使得Win32上运行的程序可以容易地移植到Linux上运行。
而MKS公司的NuTCRACKER则是在Win32系统上虚拟了一般Unix系统使用的X-Window等环境,使得Unix上的软件可以在Win32上运行,而且仍然支持原来的图形处理功能。
目前在PC机上做得比较彻底的虚拟技术是OS on OS,典型的代表是Vmware公司的产品和PCShare公司的产品。这两个公司的软件可以在一台Windows的计算机上同时模拟出多台不同的OS的虚拟机,其中包括Linux、Solaris、OS/2等。这些虚拟机出来的计算机就像物理上的独立计算机一样工作,这对软件的测试、演示系统的搭建帮助非凡。Vmware的 Linux版本甚至可以在Linux上模拟出Windows、Solaris等OS系统。
虚拟的优点很多,但虚拟的代价也很大,主要体现在降低了执行的效率。道路很简单,虚拟在机器指令层模拟了一台计算机,但实际上它是用软件模拟了原来硬件实现的功能,凡是需要CPU执行的指令都需要在虚拟机上被重新分析,这自然降低了效率。所以在,一般情况下,虚拟技术比较合适快速地做出原型,快速地占领市场。当软件的效率被用户和厂家关注时,还是要转向前面提到的移植和跨平台模块技术。
 

你可能感兴趣的:(跨平台软件的开发方式)