随着各种跨平台语言,工具等的不断完善,越来越多的工具或软件开发都开始考虑软件的跨平台特性,而Java语言可以说是这方面最成功的产品,而它由于采用的是中间语言,并非实际的本地语言,所以在性能上,特别是在客户端产品上并不那么优秀,当然,在服务端,它的表现可以说是非常优秀的,我们的服务器大多硬件性能很好,并且可以不断的扩展,如现在的云计算平台,而我们的客户机,普通用户的电脑,性能并不那么美好,而且客户端软件的非单一性(各种软件:办公软件,游戏软件等等),使性能成为瓶颈,所以Java虽然在客户端的性能一直在改善,但性能一直是它的缺点,我想在未来很长时间都是无法改善的。
这就是为什么大多数客户端软件都采用C/C++编写的原故了,那么有没有什么办法即可以用本地化语言编写,又可以在不同的平台的运行呢?可以说有,也可以说没有,目前由于各种操作系统采用的是不同的内核,不同的文件格式,所以没有,而我们又可以通过对相同代码通过工具编译成不同平台的软件,它又可以说有。
那么,我们今天要讨论的就是:同一代码,通过编译器编译成不同平台的软件。相较java等中间代码的语言,它的优势就是本地化语言运行,速度更快,跨平台性虽然需要重新编译,但我们的核心:代码 是不需要修改的,这样可以很大节约成本。
同时对跨平台本地语言也不要太过乐观,它虽然可以达到同一代码,编译成不同平台的本地语言,但这也是有代价的,这种语言或工具,都需要基于一种平台,然后将API接口进行本地化转换,而目前由于windows的不开放性,使这一部分工作变得异常艰难,同时由于需要本地化转换,相较本地化程序,性能略有降低,同时稳定性也略有降低,开发难度也略增。
本文将介绍这种跨平台本地化转换的入口程序,以及编译方法:
1. 不同的入口与相同的入口
我们知道windows 32的入口代码如下:
int WINAPIWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSCTR lpCmdLine,int nCmdShow)
而WindowsDos和Linux的入口代码如下:
int main(int argc,char* argv[])
我们一般编写的代码都有窗口,即GUI, 目前支持跨平台的GUI比较多,比较流行和稳定的有QT, wxWidgets,GTK+等, 这三者的比较网络上有很多介绍,下面介绍入口函数的编写:
1) wxWidgets
Win32for VS2010:
#include <wx/wx.h>
int WINAPIWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSCTR lpCmdLine,int nCmdShow)
{
MyApp* app=new MyApp();
wxApp::SetInstance(app);
returnwxEntry(hInstance,hPrevInstance,lpCmdLine,nCmdShow);
}
Win32for Eclipse:
int main(int argc,char* argv[])
{
MyApp* app=new MyApp();
wxApp::SetInstance(app);
returnwxEntry(argc,argv);
}
编译时,如键点击项目名称->Properties->C/C++Build->Settings->Tool Settings->MinGW C++Linker->Miscellaneous->Linker flags->-mwindows
2) QT
3) GTK+
2. 软件图标
创建一个文本文件,扩展名为.rc, 然后输入下面代码
1ICON "app.ico"
编译.rc 到.o
windresapp.rc app.o
将资源链接到你的执行文件中
gccother.o files.o etc.o app.o -o app.exe
3. 动态库装载
在linux下有dlopen等函数,在dlfcn.h头文件中,网上有一个将win32接口转换成linux下接口形式的库:http://code.google.com/p/dlfcn-win32
可以在头文件包含时,用宏来区分不同的系统。
4. 解决依赖与统一加载接口: Libtool, GLib
综上所述,我们可以将GUI实现与接口分离,这样,我们就可以关注到我们的业务,而不管GUI是采用QT,wxWidgets, 或GTK+了,同时,可以通过插件模式,将各个模块进行分离,而入口自然推荐使用intmain (int argc, char* argv[])了,在入口处实现插件框架,GUI,业务等通过插件实现,可以实现积木的开发模式了。以下为推荐开发方式:
1. 入口: int main (int argc, char* argv[]),注意如果要实现unicode模式,有额外的工作要做。
2. 入口处即实现插件模式,splash, GUI, 业务等都通过插件实现。
动态库在开发时用dlopen,如果开发时用libtool的加载接口,将无法调试 (目前没有很好的调试工具支持libtool), 可以在代码中用宏来区分是开发模式还是产品模式
或用gmodule加载动态库