Windows API技术的演化
来源:互联网 发布:逆战显示网络连接断开 编辑:程序博客网 时间:2024/06/04 19:48
概述
从Windows 1.0 到Windows 10,对于普通用户来说,显而易见地,用户界面已经发生了很多变化。
对于Windows的开发者来说,伴随着Windows系统的不断发展,API技术演化也已经在不知不觉经历了好几代的变化。
演化
为了便于比较和讨论,本文将API技术分为5代。
第一代:C风格的API(Win32API)
Windows主要是用C语言开发的,第一代的API使用C风格也是意料之中。这一类API看上去简单高效,但由于缺少封装,参数往往过于复杂。比如说,创建窗口的函数CreateWindow,要填写11个参数。在没有代码智能提示的时代,要记住每个函数的参数也是醉了。
第二代:C++Class Library (MFC)
面向对象风潮来袭,微软用C++对Win32 API进行了一次改头换面的“装修”,创建了Windows平台开发的基础类库,也就是后来著名的MFC。从此,程序员们告别了创建窗口需要11个参数的日子,程序有 “对象” 了,世界也美好了。但是,由于C++缺少一个二进制级别的标准,却给C++类库风格的API带来了意想不到的隐患(我将会在后续的小实验中做展示)。
第三代:COM(DirectX,Office)
COM通过分离接口和实现弥补了C++没有二进制级别标准的不足,确保了模块的稳定性。它的首次应用是OLE2.0 。接口化编程和引用计数的思想对当时面向对象的C++程序员来说是个思维上的冲击,这让当时的开发者们有些不太适应(COM本质论的作者DON当时也认为使用COM是一个 “噩梦” ,直到他顿悟了COM的精髓,写下COM本质论)。另外,由于微软当时急于推出OLE2.0,导致COM文档的缺乏,这给COM的使用和推广带来了不利。
第四代:.NET(WindowsForm, WPF)
.NET的出现,开启了Windows开发的托管语言时代。从API的角度来说,它的稳定性和易用性上比前三代API都要出色,但它有一个硬伤---性能。虽说随着硬件的发展,相比于.NET所带来的开发效率, 它所带来的性能损耗似乎 “情有可原” 。但在移动开发时代,使用.NET作为基础API所带来的性能损耗就不容小觑了。
第五代:WindowsRuntime API
在前四代API的基础上,WindowsRuntime在稳定性,易用性和性能三者中找到了一个新的平衡点。它本身建立在COM之上,遗传了COM的性能优势;受.NET的启发,WindowsMetadata技术大大简化了 COM使用的复杂性,使得WindowsRuntime类的使用如普通的.NET类一样简单,在C#中使用WINRT的类,几乎看不出差别。
实验
下面我们做一个小实验,体验一下5代API的演化过程。
假设现在有这样一个需求:查找给定字符串在文本中的位置,并返回文本的总长度。
C风格API设计如下:
int FindInString(charconst * pcText,charconst * pcFind,int * piLength);
一个如此简单的功能,就需要3个参数,如果功能再复杂一些,比如设置查找选项(是否忽略大小写),那就只能通过添加新的参数了。
为了便于使用,我们将它封装为C++的类库:
class __declspec(dllexport)StringFinder{ char const * m_psz;public: StringFinder(const char * psz); ~StringFinder(); int Length(void)const; int Find(constchar * psz)const;};
看上去好多了,把这个API命名为SF1.0。
假设Length函数的实现是每次都调用strlen方法去计算字符串的长度。由于查找的文本是不变的,从性能优化的角度,我们只需计算一次长度,并将结果缓存在一个私有成员变量中。由于是私有成员变量,对原来的公开API并并不会造成破坏。所以开发人员果断而又快速地修改了代码:
class __declspec(dllexport)StringFinder{ int m_length; char const * m_psz;public: StringFinder(const char * psz); ~StringFinder(); int Length(void)const; int Find(constchar * psz)const;};
在编译和测试完成后,把这个版本命名为SF1.1,开发者将老的DLL替换为新的DLL以提高程序性能。但当用户运行程序后,尴尬的事情发生了。。。
由于添加了新的成员变量,老的成员变量在内存中的位置已经产生了偏移,由于原先的程序依然使用老的偏移量来寻址,导致了错误的发生。最后,开发人员只能将新的DLL命名为SF1.1.DLL来和原先的SF.DLL进行区分(这也是MFC解决版本问题的方式)。这样,每个版本的API都通过版本名称被相应地加载进去,虽然看上去有点糟糕,但至少勉强解决了问题。
反思根本原因,是因为在C++类库版本的API中暴露了实现类StringFinder。那么有没有办法不暴露实现类而又能对功能进行封装呢?为了解决这个问题,我将StringFinder类拆封为接口和实现两个部分。
// public interfacestruct IStringFinder { virtual int Length(void)const = 0; virtual int Find(constchar * psz)const = 0;}; __declspec(dllexport)void CreateStringFinder( IStringFinder ** finder, const char * psz);// implement classclass StringFinder :publicIStringFinder{ int m_length; char const * m_psz;public: StringFinder(const char * psz); ~StringFinder(); int Length(void)const; int Find(constchar * psz)const;};
由于实现类StringFinder不对外暴露,所以类内部的实现对于调用者来说是透明的,这就是COM接口的基本思想。
C++没有二进制标准的遗留的问题解决了。但是从API的使用者角度来说,COM这种接口式编程和引用计数的方式比较繁琐,影响开发效率。有没有一种让API的稳定性和生产力兼备的API技术呢?
让我们来看一下.NET的实现方式:
public classStringFinder { private readonlystring text; StringFinder(string t) { text = t; } public int Length {get { … } } public int Find(string find) { …; }}
这种实现方式中,API的安全性和开发效率上都有所提高,但在程序的性能却要逊色于前3代的API技术。
最后,让我们使用WindowsRuntime (CX)来进行实现:
namespace WRCStringFinder{ public refclassStringFindersealed { Platform::String^ m_text; public: StringFinder(Platform::String^ text); int Length(); int Find(Platform::String^ find); };}
现在,我们甚至可以在.NET, C++和JavaScript三个语言平台上调用这套API,并且具备C++的性能和.NET的效率。
小结
上面简单讨论了WindowsAPI技术演化过程,个人理解,欢迎拍砖。每种技术都有其各自出现的背景和要解决的问题,不能说那种绝对好,哪种绝对不好。
在接下来的文章中,我会具体介绍Windows Runtime的基本原理和使用实践。
- Windows API技术的演化
- 恶意代码检测技术的演化
- 恶意代码检测技术的演化
- windows下的api hooking技术
- 基于Windows API的Socket程序技术
- 买单侠微服务的API网关演化之路
- 网站技术笔记-演化
- P2P与IPTV的技术演化进展4
- P2P与IPTV的技术演化进展3
- P2P与IPTV的技术演化进展2
- P2P与IPTV的技术演化进展1
- Windows 图形界面演化
- C#中调用Windows API的技术要点
- C#中调用Windows API的技术要点
- Windows下Hook API技术
- Windows下Hook API技术
- Windows下Hook API技术
- Windows下Hook API技术
- 减少AWS费用的一些边边角角
- 安装intelhaxm出错,this computer does not support intel virtualization Technology(VT-x)
- 改善Java文档的理由、建议和技巧
- 破解&屏蔽防止嵌入框架代码 top.location != self.location
- Android 友盟更新
- Windows API技术的演化
- This Handler class should be static or leaks might occur Android
- 如何在eclipse中快速创建Activity
- thinkpad 左键变成右键 or 自动点右键
- 简析truncate和delete的区别
- 函数式编程
- 高阶函数
- 大整数的加乘多项式运算
- 生鲜电商的七种模式分析