买了mac好久,也是时候搞点高科技了,作为程序员的天性,总喜欢研究东西是怎么开发出来的,正好最近也闲来无事,研究一下Mac下是如何开发软件的,笔者本身是个win32程序员,发现mac下的软件多少同windows有点类似,特别是carbon。


Mac Os X本身是个类Unix的操作系统,据帮助文档说,OS X拥有unix强壮的文件系统,内存保护机制,BSD的系统服务及工具,在Mac OS X下支持多种程序开发环境,他们分别是
Cocoa,一种面向对象的程序接口,使用Objective C实现,这是苹果推荐的开发环境,笔者本身对Obj C不熟悉,我也不清楚苹果为什么推荐使用Obj C,使用gcc作为编译器。
Carbon,一种过程化的程序接口,使用c、c++实现,也是使用gcc作为编译器,是苹果传统的开发环境。
Java,不多说了,反正我对Java不感冒。
BSD,通过开源Drawin API开发。
还有经典的Mac OS 9或更早的Mac OS系统开发环境。

前面已经说了,笔者本身是win32程序员,所以对同win32很类似的Carbon环境比较有兴趣,如果我的后续文章也会使用Carbon作为基础来讨论Mac OS X的软件开发。

虽然Carbon使用了完全不同的数据结构来描述程序结构,但不能否认的是,它真的同win32很类似,简单来说它也是通过事件驱动(win32 是消息驱动),系统会发送特定的事件到特定的目标,事件也有相应的处理函数(Event Handler)来处理对应的事件,这点也类似win32的消息处理函数。

Carbon使用EventRef结构来描述事件,这个结构对于程序员来说,是透明的,程序员不需要关注结构的内部数据成员,这类似于win32的Handle的概念,Carbon提供了一系列函数用于从EventRef结构中获得你需要的数据,这些函数包括:
获取事件的类型,比如是键盘事件,还是菜单事件;
获取事件的种类,比如是键盘按下,还是松开;
事件发生的时间;
事件对应的特定参数,这个类似win32的wparam和lparam参数。

对于特定的参数,是说在你知道事件的类型、种类后,可以使用GetEventParameter函数来获取这些参数,调用这个函数的时候,你需要知道参数的名字和类型。

同win32一样,事件也对应有相应的处理函数,用于相应事件,而与win32不同的是,Carbon的事件处理是堆栈结构,默认的处理函数位于堆栈的底端,自己的事件出来函数插入在中间合适的位置,并返回时候处理了对应的事件,用于通知系统。所以carbon中需要处理的事件是需要手动install通知系统的,而不是类似win32在定义窗体的时候给定一个消息处理函数。win32的消息处理函数是可以在一个函数中处理全部的消息,而carbon则是根据需要安装感兴趣的事件处理器,这两种设计各有利弊吧,无所谓好于不好,win32唯一不好的影响可能是容易造成很长的switch case段,不过这个问题在mfc中已经妥善解决了。

最后值得一提的是,Mac的Bundles概念,我感觉这个设计要比win32好很多,在Mac下有多种boundles,其中之一就是程序boundles,所谓bundles就是一个特殊的文件夹,这个文件夹里放置了一个程序全部的东西,包括可执行文件,数据,资源,在Mac下,boudles会显示成一个单一的图标,用于表示这个文件夹,你可以直接双击这个特殊的文件夹来启动程序,而不需要关心程序内部结构、数据,让最终用户不至于迷惑,在删除的时候,也是直接删除文件夹,在最终用户看来,操作的对象都是boundles。而在开发阶段,这个概念就贯穿始末,mac的开发工具xcode就是基于boundles发布程序,只要你build完成,你就可以立刻发布boundles。