缘由
经常听到一些刚刚接触Windows Embedded CE和Windows Mobile开发的人会提出一些疑问。进行Windows Mobile开发,到底使用什么语言呢?C++还是C#?Java行不行?下面就我自己的想法讲述一下Native C++ 和 .NET Compact Framework的异同和选择。
什么是Native
Native翻译成原生,Native是使用C,C++或者汇编等语言代码编写的,编译成处理器相关的binary文件(执行文件,DLL等可执行文件), 关于可执行文件可以参考http://en.wikipedia.org/wiki/Portable_Executable 。当前Windows Embedded CE和Windows Mobile支持的硬件平台包括x86, MIPS, ARM和SuperH。由于各个平台之间的指令集不一样,所以可执行文件不能互相支持其他平台。使用Native 开发,程序不依赖于任何其他子系统,例如.NET Compact Framework运行环境,JVM运行环境等,但是一套程序必须为各个硬件平台编译不同的可执行文件。
什么是.NET Compact Framework
基于.NET Compact Framework开发的程序,可以叫做托管程序,英文叫做Managed code。所谓Managed code就是使用C#,VB.NET语言来编写代码,使用.NET Compact Framework来开发,编译成平台无关的中间语言(Intermediate Lanuage, IL)的文件的程序。基于.NET Compact Framework开发的程序,在编写的时候会使用到.NET Compact Framework 基础类库(.NET Compact Framework Base Class Libraries, BCL) ,BCL为应用程序提供API。托管程序在运行的时候会使用到运行时执行引擎(run-time Execution Engine, EE), BCL和EE统称为Common Language Runtime (CLR)。当托管程序首次执行的时候,CLR会把IL文件编译成相关平台的binary文件(可执行文件)。这个过程叫做Just-In-Time (JIT) compilation。由于有了这一个过程,所以所有托管代码都依赖于CLR,因此,需要运行托管代码的设备必须安装 .NET Compact Framework。
图来自于Windows Embedded CE 6.0 Fundamentals Chapter 9.
通俗化Native Code vs. Managed Code
上面讲述了一堆理论的东西,下面使用一个通俗但不是很贴切的例子讲述Native和Managed,Native翻译成原生,其实有地道的,与生俱来的意思,例如你天生说普通话,那么可以说你是Mandarin Native Speaker。也就是与生俱来说普通话,地地道道的普通话。如果你要做一些语言相关的产品进行销售,如果你在销售产品之前把之翻译成各个语言,例如在国内销售翻译成中文,在美国翻译成英文,在日本翻译成日文,这好比你使用Native Code来开发,在编译时已经为各个硬件平台生成原生的机器代码。但是Managed(托管)代码就好比世界语,世界上没有那个民族和地区天生就说世界语,但是你使用世界语来销售你的产品。针对每个不同国家和地区,你附送一个及时翻译机,这个翻译机会在用户使用的时候把世界语翻译成当地原生语言。这就好比基于.NET Compact Framework开发的代码,需要CLR来翻译执行。这里注意不同硬件平台CLR是不一样的,他们功能都是把IL编译成Native的机器码,但是各个平台的机器码不一样,所以.NET Compact Framework也不一样。.NET Compact Framework帮你处理了平台差异性,因此.NET Compact Framework的程序是跨平台的,就像世界语加上翻译机那样,基于.NET Compact Framework编写的代码可以支持任何平台,前提是微软为具体平台实现CLR。例如大家都知道Yahoo,其实世界上有一种快要消失的语言就叫做Yahoo,如果你做一个世界语到Yahoo语的翻译机,那么你的产品可以不做任何修改就卖到讲Yahoo语的地方了。
理论讲Native Code vs. Managed Code
Native Code |
Managed Code |
编译成平台相关的机器码 | 编译成IL(Intermediate Language) |
一次编译,各种设备到处运行 | 为各个不同设备编译不同版本 |
不需要其他框架支持(相对于.NET Compact Framework来说) | 需要CLR支持,也就是需要安装.NET Compact Framework Rumtime |
可以最大限度的访问系统提供的API和服务 | 只能访问.NET Compact Framework 提供的服务,例如WIFI和Bluetooth,.NET Compact Framework 的BCL不提供支持,所以如果只是使用.NET Compact Framework 是不能进行WIFI和Bluetooth的开发的。 由于有上述的限制性,所以微软提供P/Invoke来访问平台相关的API和COM。 |
可以使用MFC,ATL,WTL,STL等库进行开发 | 可以使用.NET Compact Framework 的BCL进行开发 |
如何选择Native Code和Managed Code
了解了Native Code 和 Managed Code的异同,可以根据其特点和相应的需求进行选择。没有绝对的好坏,所以才存在两个平台同时存在的现状。
Native Code开发速度相对慢一些,因为没有.NET Compact Framework 的Base Class Libraries的支持。BCL为开发者做了大量的封装,例如Garbage Collection,Windows form,Web Service等等。基于BCL开发者可以专注于业务的开发。所以使用.NET Compact Framework一般来说可以节省不少开发时间。时至今日,库对语言的影响越来越多,如果没有RoR,Ruby可能还是一个籍籍无名的日本方言。C++之父Bjarne Stroustrup说,C++的扩展更多的在STL的扩展,通过STL来支持新特性,以此C++从语法上一直没有大变化,但是由于STL的不断扩展而不断带来新的活力。可见库对一个语言和开发人员的重要性。在这方面.NET Compact Framework 胜出,但是Native C++还是可以通过MFC,ATL,WTL,STL来补救。我本人十分喜欢使用WTL处理界面和大量使用STL,关于WTL,可以参考:
Windows Mobile和Wince(Windows Embedded CE)下的WTL(Windows Template Library)开发
Windows Mobile 和 Wince(Windows Embedded CE) 下的 WTL(Windows Template Library) 界面(UI)开发
Windows Mobile和Wince下使用WTL进行Windows Media Player开发
Windows Mobile下使用Native C++(WTL, MFC, Win32)开发,如何为对话框加入菜单
Windows Mobile下如何去掉WTL对话框CStdDialogImpl的OK按钮
在Windows Mobile下使用WTL进行Native C++开发,如何显示等待图标
在Windows Mobile和Wince(Windows Embedded CE)下进行WTL开发,如何加入超链接(HyperLink)
但是Native Code执行速度相对快,因为基于.NET Compact Framework 的代码有JIT的过程,第一次执行需要把IL编译到Native机器码,而Native Code本身就是机器码,所以Native Code快很多。
同时Native Code使用的memory footprint也少很多很多,Native Code使用的footprint只是和你编写的代码分配内存有关。但是基于.NET Compact Framework 的代码,尽管一个几乎没有任何功能的程序,启动的时候也需要1到2M的内存。这些内存用于处理Garbage Collection等用途。
Native Code和Managed Code存在一个可控性的gap,.NET Compact Framework 是.NET Framework的精装版,封装了一部分.NET Framework的功能,但是不完全包含.NET Framework的所有功能。Native Code具有完全访问系统API和服务,平台API的能力,而.NET Framework不完全具备,.NET Compact Framework 就更加不具备,所以从系统可操控性来说,Native Code和Managed Code存在一个gap,这个gap是指有些功能Native Code可以做,但是Managed Code却无法实现的功能,例如WIFI,Bluetooth。要在.NET Compact Framework 实现这些功能必须通过P/Invoke来实现,关于P/Invoke可以参考一下
.NET Compact Framework 下Win32 API P/Invoke 的使用
如何在Windows Mobile下使用Native C++动态加载DLL
Windows Mobile和Wince(Windows Embedded CE)下如何封装Native DLL提供给.NET Compact Framework进行调用
Windows Mobile和Wince(Windows Embedded CE)下封装Native DLL进一步探讨
在Windows Mobile和Wince(Windows Embedded CE)下封装Native DLL的回调函数
由于这个可控性的gap的存在,所以出现了OpenNETCF的Smart Device Framework,32feet.net等库,这些库为基于.NET Compact Framework的程序封装了P/Invoke的调用,这样减少了gap的存在。32feet.net可以参考 基于32feet.net对Broadcom(Widcomm) stack蓝牙(Bluetooth)设备开发Windows Mobile与PC程序 等系列文章。当然微软也不断的在填补这个gap,.NET Compact Framework的不断升级,这个gap越来越小了,例如.NET Compact Framework 1.0没有串口操作,但是在.NET Compact Framework 2.0已经加上。可是.NET Compact Framework的rumtime就越来越大,同时启动也越来越慢,任何都是均衡,移动设备受到CPU速度和内存的限制,.NET Compact Framework 并不是加入越多功能越好。过犹不及,中国人常说的。
Balabala...说那么多还是没有说到底如何选择,其实是trade-off(均衡),没有绝对真理,还是根据具体需求,结合上述Native Code和Managed Code的特点来选择。我自己的经验,如果速度要求快,内存要求少的核心模块都是使用Native C++(一般包括无界面,纯数据处理的程序和完全自定义界面的GDI程序),其他模块都用.NET Compact Framework。如果一个模块需要大量使用P/Invoke,也是需要考虑使用Native C++来代替.NET Compact Framework的。目前觉得选择还是OK的。
写到这里,希望看官能明白,有疑问请回复交流。下午Christmas party, happy去。