现在的位置: 首页 > 综合 > 正文

我喜欢Symbian

2013年04月25日 ⁄ 综合 ⁄ 共 2319字 ⁄ 字号 评论关闭
Symbian 是Nokia,爱立信等高端PDA手机中常用的一个操作系统, 原生的SDK是C++, 所有的API都是直接使用C++语法, 当然为了兼容的原因, 仍然提供了标准C library, 不过功能并不完善, 在symbian中也不推荐使用, 不过我觉得用也无妨,, 因为C的接口比较简单.

Symbian是一个比较陈旧的操作系统, 使用C++开发的时间大概在90年代早期, 基本上没有用到什么高深的C++特性, 例如STL等, 当时C++编译器也没有现在这么高级. 现在看, 我个人认为Symbian是一款较差的融合了C/C++/Java等各种语言的缺点,( 当然当时还没有Java), 而组合成的一个预计在未来不超过10年的时间需要被进行大幅度整改的基于C++的操作系统, 其中它对C++语义的无情摧残和丑陋的Leave机制, 基本上使得在Symbian上开发C++完全就像在走钢丝, 使得C++语言中提供的一个及其重要的特性"确定性析构" 无法在Symbian上得到保证.

没有确定性析构, 就没有RAII, Symbian中没有异常, 因此就使用了一种类似C中longjmp的机制, 由于longjmp并不自动进行stack unwind, 因此Symbian提供了Cleanup Stack, 要求程序员手工将执行析构动作的函数指针填入一个Stack列表中, 当longjmp(leave)的时候, 会一一调用在这个Stack中的函数, 以释放资源.

基本上来说, 对比现在的C++异常, Leave机制基本上没有提供任何比C++异常好的地方, 无论是效率还是内存消耗, 而且Leave机制具有错误倾向. 毕竟这些事情人还是不如编译器.

Symbian为了满足它的Leave机制, 提供了几个T,C,R,M class类别.

C class:
   所有原本具有non-trivial构造函数的class按照Symbian的定义, 都应该是一个C class. 需要采用两阶段构造, 先new一块内存, 然后在构造函数中不能再进行任何内存分配等任何可能引发Leave的函数, 也就是保证ctor必须成功, 然后在提供另外一个函数在进行必要的初始化, 这个在Symbian中一般命名为ConstructL. 为了避免程序员不小心漏过ConstructL, 因此一般这个构造函数都不是public, 而提供一个静态的NewL或者NewLC静态工厂函数返回新创建的对象的指针. 如下:
   class CFoo
   {
   public:
     static CFoo* NewL();
     ~CFoo();
   protected:
     CFoo();
     void ConstructL();
   };

得到这个指针以后, 为了实现Leave完全( symbian SDK中的不少函数内部都是Leave的) , 因此必须对这个裸指针进行保护. auto_ptr? 别做梦了, 前面说来Leave机制发生的时候没有确定性析构. 因此需要将这个对象手动插入到Stack中,  见#1

  CFoo * foo = CFoo::NewL();
  CleanupStack::PushL(foo);         #1
 
  do_sth(..);
 
  CleanupStack::PopAndDestroy(1);   #2

还要写一个#2, 调用foo的析构函数.

而由于PushL需要调用Foo的析构函数, 因此这个Foo应该继承自一个基类, 以使得析构函数为virtual. Symbian提供了一个class用于被所有的C class继承, 即CBase. 因此我们的CFoo 就应该从CBase继承.

 对比有C++ Exception的实现, 程序员可以:
 CFoo foo;
 do_sth(..);

对比上面使用Leave机制的例子, 哪个好一目了然.

由于C class的特性, 决定了Symbian中很难使用多重实现继承, 这个并不是太大问题. 但是要求所有的C Class都必须分配在Heap中, 就有点类似"纯OO"Java的味道了, 但是又没有GC可用, 因此大量的登记工作就全留给程序员了. 而且从Heap中分配和从Stack中分配速度相差不少.

又如果你一个大的C class包含有2个其他的C class作为成员变量, 对了, 那也是你最爽的一种.
这两个C class对象也必须使用New的方式创建出来. 也就是C++中的Pimpl手法.

R class 同样, 还是类似 "纯OO"的Java, 提供一个Close()函数释放资源, 基本上都是C++中最难用的方法.

还有一点就是Symbian中的DLL不能有data段, 也就是没有静态数据. 没有静态数据连个singleton都实现不了, 更别提其他的用处了.Symbian的大概解释是: 一个DLL如果有静态数据, 那么对于每个调用了这个DLL的Process都需要分配一个内存块, 最小的单位是4K. 因此如果一个DLL被N个进程使用, 那么即使只有一个字节的静态数据, 浪费的大小也是 N * 4K, 因此不可接受.

明智之举!!

我写的DLL从来就是我自己公司的一个破烂程序使用, 别人根本就不调用我的DLL, 因此根本没有N个进程, 因此也就浪费4K. 而且我程序越大, 需要的静态数据就越大, 因此4K最小分配单位根本就不是一个问题.

系统的DLL可是被很多进程调用的啊? 这个开销可不少啊. 对啊, 但是系统的DLL又不是我写的, 是你们这些绝顶聪明之人所为, 你可以不用啊. 为什么要限制我们使用了?

还有一本中文版的Symbian的书好像说到一点: Symbian的这些genius为了防止我们这些傻瓜们滥用静态数据,  因此干脆就去除了这个特性.

这个解释我最喜欢, 也觉得最合理, 符合C/C++的传统精神: 程序员都是傻瓜.

我喜欢Symbian!!

【上篇】
【下篇】

抱歉!评论已关闭.