序:去年为了总结自己所学习/接触过的技术,也顺便为初学者少走弯路指明一些方向,可惜后来诸事缠身未能继续,十分遗憾,现放到自己的BLOG上来鼓励自己将此继续下去。
  "Win32编程”
  很不幸,我从开始学习编程到理解这个名词中间隔了很长的时间(上个世纪的学习环境可见一斑)。很长时间里我都不明白32是指什么,我用过Dos,Win31,win95,win97...但好像没用过名为Win32的操作系统啊?很久以后我才知道,32在这里并不是指操作系统的版本号,而是指32位。微软操作系统在win31及其以前都是DOS系统,windows只是在dos下运行的一个大程序而已。在其后win95则稍有改变,windows除了DOS核心以外也真正成为了操作系统的一部分,提供着各类操作系统提供的服务。应该说,在win95之后的windows(新近的64位win系统以前)都可以称之为win32系统平台(95/98实际上是16与32位混合)。所以在这样的平台上,直接或间接使用系统提供的API编程,称之为Win32编程。对Visual Studio而言,Win32编程一般指SDK、MFC、ATL这几类开发方法,其中ATL在国内应用不是很广泛,一般应用于以COM组件为架构的中大型软件产品。
  "SDK":Software Development Kit,常译为软件开发(工具)包
  在Win32编程领域一般指与MFC这类框架编程相区别的,直接调用Windows提供的API的开发方式,与字面原意有一些区别。另外一个经常见到的说法是某软件(硬件)带有自己的一套SDK,这里其实一般是指一套API库函数或者类库,供上一层的开发者调用。又譬如常说的DX的SDK,其实是微软开发的一套COM组件,供上层开发者使用。总之,供程序员使用的比较完备的代码库,可以称之为SDK;
  “MFC”:Microsoft Fundation classes微软基础类库
  大家都知道,使用SDK编程方式往往有很多每次都重复的固定不变的一些代码,为了提高编程的效率,减少上千个API带给开发人员巨大的精神压力,微软开发出了这么一个类库,注意,这个类库与操作系统本身无任何关系,它只是对API进行了一个面向对象的封装,当然,还给出了一系列编程的框架。使用SDK的方法,使用Visual Studio,通过调用Windows API,MFC你也可以做得出来。MFC把一些固定不变的代码已经写好了,只在编译时候链上,所以我们的代码里看不到WinMain(),而事实上整个程序的运行,和SDK的方式无任何区别,初学者请记住这一点。另,补充一点个人感想,MFC的初衷,带给开发人员更多的便利,我觉得并不太成功。学习MFC所费的力气和终的所得,并不太成正比。
  "API":Application Programming Interface,应用程序接口
  这个词的出现频率很高,从某种意义上来说,也可以看作是SDK的一个子集。这也是做给程序员的程序,不过一般指用导出函数的方式提供服务的函数库,不包括类库和组件。
  “GDI”:Graphic Device Interface,图形设备接口
  这个是Win32程序下常用的显示方式,与DirectX、OpenGL处于同一级。在DOS要显示一些东东可不是容易的事,简单的是调用一些C的图形库函数来实现显示,不过一般也是些画线,填色,输出几个文字,效果很弱(所以DOS程序界面一般都不怎么样,且实现起来不是一般的复杂),要复杂一点的动画/图片显示什么的,经常要用到的是硬件中断,调用一些显卡自身的子程序(固化在显卡内的)来做。因为每一个显卡都不同,所以DOS的游戏兼容常常由于显卡的差异而很糟糕。到Windows下大家幸福多了,Windows将硬件这一层屏蔽起来,用一个表格(Device Context)来代表一个显示,我们要做的是在这个表格上填好相关参数,然后画上我们想画的东东,然后操作系统会依照这个表格(DC),把相应的显示内容(一般是一块显示内存)传送到指定显卡的指定的显存,再由显卡传给显示屏。我们不再需要与不同的显卡打交通,这是一个十分伟大的胜利!GDI中常用的是双缓存技术,是说你可以在内存中创建(也是复制)一个DC,只不过在这个DC中显示的不再被传送到显示器上。有什么用呢?因为它的各参数是与当前屏幕DC一致的(COPY嘛,当然是这个结果),所以它的显示内容可以完整无失真地传送到屏幕DC上。我们通常在内存DC上画图,譬如画一圆,再画一条直线,画完后一次性地传送到屏幕DC上,这样对用户来说屏幕只刷新了一次,可以解决你画一点内容屏幕即刷新一次导致的闪烁问题。当然,双缓冲甚至多缓冲还有很多别的用处,那要靠自己揣摩了。
  "DirectX"
  通常简称为DX(读音:低叉)这是个很吸引人眼球的名词,读起来很上口:)。Windows为我们作了许多屏蔽底层硬件的工作,其中DX是知名的技术之一。操作系统要与各类硬件打交道,特别是多媒体相关的,譬如显卡、声卡、手柄输入、多媒体流的网络传输等等,这些事情如果都自己来弄的话,那太要命了(这些一般都涉及系统底层,自己也很难做出来)。而DX则正是这么一套操作系统提供的隔离多媒体硬件与程序员的间质,DX自身一般并不实现处理的能力,它是一个标准,要求硬件来满足,好比DX提供一个函数名,硬件来实现函数内容一样。通过它我们可以非常简单而快速地调用硬件提供的各类服务。它主要包括DirectDraw(通过直接访问显示硬件来提供快速的图象处理能力),DirectSound(提供了软硬件的低延迟声音混频和回放,以及直接访问音频设备的能力),DirectPlay(它明确的提供了通用环境连接能力来简化你应用程序之间的通讯服务),Direct3D(DirectDraw的3D版),DirectInput(简化你的应用程序访问鼠标、键盘和操纵杆设备的能力),DX5.0之后又增加了一些(如DirectShow),不再详述。DX一个重要的特点是你可以通过它直接访问硬件而无需知道硬件的具体细节。譬如DirectDraw,能够越过内存而直接访问显存,这样的速度将比GDI快很多,不在一个数量级上。补充一点:DX是以组件的方式提供的,而不是通常的导出API的形式。DX SDK的新版本是9.0
  "COM”:component object model,组件对象模型,一般简称组件
  这是微软为了解决代码重用的一个重要机制。重用代码的简单办法是源代码重用,把写好的函数和类加到自己当前的代码中,编译即可。简单是简单,敝病却显然的多。另一个常用的方法是单独做成模块,以DLL的形式分发,DLL导出函数或者类,客户程序用动态/静态链接的方法将其加载,这显然比前一种源代码的方法好一些,难度也不大,为常用。但DLL也有一些不足,根本的,它不是二进制兼容,DLL版本升级一次需要与客户程序代码重链接一次,有些时候这几乎是不可能的任务。为了更好地让编程像“搭积木”一样简单,让模块可以完美地配合,完美地替换,COM产生了。COM不是类库,不是代码,不是操作系统的服务,而是一套编程模型,理论上来说,它与语言无关,与操作系统无关,unix下同样可以做COM。COM是一种程序结构模型标准,你做的DLL或EXE在结构上满足这么一个标准,那这个DLL或EXE是一个组件,它将在该平台上成为二进制兼容。COM主要利用了注册表来登记本模块的信息。客户程序调用时首先查注册表,找到所需组件的位置(这实现了位置透明),然后用Loadlibrary把它加载进来,这和普通调用没有本质区别,区别在于由于组件特殊的实现方法使得整个过程中用户程序都不知道组件的位置,组件的类的实例化过程,如何销毁,不能直接访问组件的任何实现细节,用户只与组件的几个public接口打交道。这将实现真正的模块之间的独立。对用户程序而言,对于目标组件的认识,除了接口,一无所知。在接口不变的情况下,组件可任意替换而客户程序不作任何改动,无需编译,仅这一点,在中大型程序的模块集成的过程中将节约相当多的时间。
  ?"STL":Standard Template Library,标准模板库
  这是早由Alexander Stepanov和Meng Lee(蛮像中国人的名字)完成,于1994年提交给ANSI/ISO标准C++委员会并通过而成为标准C++的一部分。望文生义即可知这是一个代码库标准,不是语法标准。简单地说,STL是以C++中的模板语法为基础建立起来的一套包含基础数据结构和算法的代码库。STL的特点是实现了“类型参数化”,即STL的代码中可处理任意自定义类型的对象,如果不使用模板技术的话,这是一件相当困难的事。也因为这个原因,在新的java及C#语法中均加入了对模板语法的支持,可见其重要性。另外一个有关STL重要的话题是GP(Generic Programming),泛型。这是与面向对象相并列的另外的一个编程模型,它以模板为基础,弱化了实体类型的差异,简化了编程时问题抽象的模型,提供了更好的封装性和弹性,对于繁杂的面向对象编程毫无疑问是一种解脱,至少是精神上的。GP并不是用来取代面向对象的,而是作为一个有益的补充体,是面向对象很好的合作伙伴。GP是近几年软件架构的一个研究热点,但国内真正的应用似乎并不多见,这项技术本身还基本处于研究前沿。<<Modern C++Design>>一书对C++中的GP应用有很好的诠释,而这本书对脑细胞的杀伤力之大,也是其它C++书藉望尘莫及的。想知道C++的代码技巧可以做到怎样的出神入化吗?不妨看看这本书。
  "ATL":Active Template Library,活动模板库
  这在VC编程下应该算是比较高级的话题了,它集COM和模板技术于一身,带来了极方便的组件编写方法和极高的学习门槛。可以说,进入ATL领域算是进入了中级以上的编程领域。ATL是为组件而生,它的目的是为了让程序员更方便地编写组件(纯用C++写一个简单的组件实现一个“Hello World”对初学者来说都是要命的),同时它使用模板技术来类似于MFC一样建立了一个开发COM的框架代码库(模板库),使用该框架及模板库可以相对方便地进行组件开发。ATL中的一个特点是你自己的类将成为ATL代码库中某些类的父类,这是一件很有趣的事(这也是模板技术的一个特点)。
  "HANDLE":句柄
  这是一个中文翻译很古怪的字,对初学者来说是百思不得其解的东东。这其实等价于void*(顺便提一下,初学者往往对VC代码中各种古怪的符号、类型标记/宏等百思不得其解,其实它们大多来自基本类型的#define或者typedef,请将光标移到这些符号上(譬如HANDLE),然后按下F12,编译器自会把你带到它的声明处,反复使用几次,你终会见到它的原貌,然后长吁一口气:原来不过如此而已。没用过的初学者请牢记:F12)。很多初学者总想知道一个HANDLE代表一个什么对象,我的建议是不要去理解为某对象,而是理解为访问某一个对象的入口,事实上HANDLE大多数时候是一个整数索引(标志该对象在操作系统的某表中的位置,好像一个数组的下标一样),Windows系统核心中主要是几张大表,这样一个整数索引是标记目标在这个表中的位置,供操作系统访问时查询用。偶而它的确是指向某对象的指针,有时它还携带一些额外辅助信息。总之,我们不要去直接访问它,把访问HANDLE的任务交给操作系统好了,除非你还嫌写程序不累:)。
  "DLL":Dynamic Link Library动态链接库
  DLL的一个特点是可以动态加载(顾名思义),即在主程序(我更喜欢称为客户程序)需要该模块时才由操作系统加载到内存。毕竟一个大型应用程序我们经常使用到的功能并不多,这样一些不常用的功能模块(DLL)在程序运行时一般将不被载入,可极大节省内存开销。DLL同时也是目前常用的分发模块的方法,便于彼此协作。程序中对DLL的调用主要有两种方法:1针对使用DEF文件导出函数的DLL,使用API函数LoadLibrary(“DLLModuleName")加载,然后使用GetProcAddress()得到函数指针,进而调用2直接将类、函数等导出,客户程序使用同一份头文件声明,加入对应的lib链接库,即可在客户程序中直接使用DLL中的类或函数,无需LoadLibrary。
  "Process":进程
  进程是一个动态的概念,包括从进程的创建申请,PCB(Process Control Block进程控制块,一般操作系统实现为一个表格(struct))的创建,地址空间的内存分配,模块代码载入并执行,执行完以后进行撤销,整个过程被称为"进程"。在Win32下,一个进程有4G的逻辑空间。但我们也常把它作为静态概念来使用,在Win32下,一个EXE的执行是一个进程(如果它内部又开了新进程,另当别论)。
  "Thread":线程
  为了更有效的提高CPU的利用率,更好地实现多任务并发,微软将进程进行进一步分割,实现了CPU任务调度的新对像:线程。一个进程拥有至少一个线程。我们在实现多任务并发的时候通常是建立一个新线程(建立线程的系统开销要小于进程),线程以我们自己的一个函数作为入口,函数执行完毕自动撤销(当然你也可以在执行过程中强制结束该线程)。顺便提一下,在UNIX下并没有线程这个概念,想来是因为UNIX主要是以多进程的并发服务为主(所以它更适合于做服务器),系统运行时通常已经有了太多的进程,所以没有必要再对进程进行细化,因为这样做甚至会降低系统效率(CPU调度不过来),当然,这是我个人的猜想:)
  "C语言"
  到目前为止,C语言应该是传播为广泛的语言,特别在UNIX的世界里依然扮演着主角的位置,在其余如硬件开发,嵌入式系统(如手机)皆有十分突出的表现,即便在win32平台下SDK的开发中也有一席之地。更主要的是它是大多数国内(国外我不敢说)程序员的启蒙语言,通过它许多人才领会了程序的思维。C大的特点是快,除了汇编以外效率可以达到高,而它的灵活性,对硬件的直访性也完全符合程序员自由的天性。如果说学习别的技术尚有犹豫和徘徊,那么学C只有一句话:相信我,没错的!也有许多人主张可以直接学习面向对象语言,我不太同意。面向对象语言对机器模型的抽象十分容易让程序员迷糊,心中难以建立准确的程序运行时的模型。毕竟我们是程序员,不是用户,我们不能把所有的问题都想当然地交给编译器和操作系统去解决,它们也解决不了。至少学习一门面向过程的语言,才能知其所以然。
  C++
  这是贝尔实验室的又一杰作,同时,也伤透了全球太多程序员的心,脑细胞杀伤力十分之大。C++比大多数初学者想像的都要复杂得多,它基本包括:一个类化了的C语言,模板,标准模板库.很多初学者掌握的C++仅仅只是一个类化了的C语言的一个子集(不相信的话,你不妨看一看<<Modern C++Design>>中的C++代码,看看能理解多少)。更麻烦的是使用C++不得不谈到面向对象的编程风格,这同样比初学者想像的难很多,要有打持久战的准备。而让我这类C++爱好者忧心的还是它目前在Win平台中的前景,在.net平台上很难找出不用C#而使用C++写新代码的理由:(。而它的复杂性和目前许多诸如java/C#及一些动态语言(python/ruby)比起来,开发效率显然的低,大有退出上层应用程序开发的趋势。这么一个包含了多范式的近乎完美的语言,我实在不想放弃。我唯有祈祷在未来C++的路可以走得更远更好一些。