当前位置:首页 >> IT/计算机 >>

symbian c++


Symbian C++开发经验
针对 S60 第三版

文档撰写人:今去冠首你你魔 文档完成日:2007 年 12 月 13 日

书剑堂·今去冠首你你魔
心存剑魔·手握魔剑·剑中含心·心中藏魔·以魔运剑·剑走心声

Symbian C++开发经验

2/36

修改记录
修改类型 创建 修改日期 2007-12-13 修改者 JqgsNinimo 描述 介绍 Symbian C++的基本使用方法

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

3/36

目录
1. 2. 3. 前言..................................................................................................................5 Symbian C++简介 ...........................................................................................6 Symbian C++开发环境搭建 ...........................................................................7 3.1. Nokia 的 Carbide..........................................................................................7 3.1.1. 针对 JAVA 的 Carbide 开发工具......................................................7 3.1.2. 针对 Symbian OS C++的 Carbide 开发工具 ...................................7 3.1.3. 实现用户界面个性化和定制化的 Carbide 工具.............................8 3.2. 基于 Microsoft Visual Studio IDE 的开发环境搭建 ..................................8 3.2.1. 安装 Carbide.vs 3.0 的必要条件 ......................................................8 3.2.2. 安装 Visual Studio 2005 ....................................................................9 3.2.3. 安装 JRE 和 ActivePerl.....................................................................9 3.2.4. 选择安装 SDK...................................................................................9 3.2.5. 安装 Carbide.vs ...............................................................................10 3.2.6. 安装完成..........................................................................................10 3.3. 基于 Eclipse IDE 的开发环境搭建...........................................................11 Symbian C++独特机制 .................................................................................12 4.1. 命名惯例 ....................................................................................................12 4.1.1. 命名总则..........................................................................................12 4.1.2. 命名前缀与命名后缀......................................................................12 4.2. 基本类型 ....................................................................................................13 4.3. 类的划分 ....................................................................................................14 4.3.1. C-Class:堆分配类.........................................................................14 4.3.2. R-Class:资源类.............................................................................14 4.3.3. T-Class:值类 .................................................................................15 4.3.4. M-Class:接口类 ............................................................................15 4.3.5. 静态类..............................................................................................15 4.3.6. D-Class.............................................................................................15 4.4. 异常处理 ....................................................................................................15 4.4.1. TRAP 和 TRAPD ............................................................................16 4.4.2. 异常抛出函数..................................................................................16 4.4.3. 可能异常退出的操作符:new(ELeave) ........................................18 4.4.4. 可能异常退出的函数......................................................................18 4.4.5. 引入清除栈(Cleanup Stack)机制 ..............................................18 4.5. 清除栈 ........................................................................................................19 4.5.1. 清除栈成员要求..............................................................................19 4.5.2. 清除栈的操作..................................................................................19 4.5.3. 清除栈弹出操作的 debug 版本......................................................21 4.5.4. 使用清除栈的注意事项..................................................................22 4.6. 两阶段构造 ................................................................................................22 4.6.1. 引入原因..........................................................................................22 4.6.2. 具体措施..........................................................................................23 4.6.3. 总结..................................................................................................24

4.

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

4/36

5.

6.

7.

S60 第三版程序框架 ....................................................................................25 5.1. 框架概述 ....................................................................................................25 5.2. 框架详解 ....................................................................................................25 5.2.1. E32Main()函数:创建应用类对象 ................................................26 5.2.2. 应用类:创建文档类对象..............................................................27 5.2.3. 文档类:创建 UI 类对象 ...............................................................28 5.2.4. UI 类:程序运行中枢 ....................................................................28 5.2.5. 视图类:程序的前台......................................................................29 5.2.6. 引擎类:程序的后台......................................................................30 5.3. 一些特殊的文件 ........................................................................................30 5.3.1. inf 文件 ............................................................................................30 5.3.2. mmp 文件 ........................................................................................31 5.3.3. pkg 文件...........................................................................................31 5.3.4. rss 文件 ............................................................................................32 5.3.5. rls 文件.............................................................................................32 5.3.6. hrh 文件 ...........................................................................................32 5.3.7. pan 文件...........................................................................................32 Symbian C++程序安装 .................................................................................33 6.1. 在 Carbide.c++ v1.2 下制作安装包 ..........................................................33 6.2. 安装过程中出现的错误提示 ....................................................................33 Symbian C++有效的学习方法 .....................................................................35 7.1. 读程序 ........................................................................................................35 7.2. 看文档 ........................................................................................................35 7.3. 逛论坛 ........................................................................................................36 7.4. 我经常访问的网站 ....................................................................................36

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

5/36

1. 前言
前段时间,用 Symbian C++开发了一款手机程序。由于首次接触 Symbian C++,致使开发过程困难重重,所幸最终一一克服。现将开发过程中的所得整 理成文,以使他人可以更加顺利地进行 Symbian C++的开发。由于我的开发是 针对 Nokia 的 S60 第三版手机的,所以文中的论述多具有针对性。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

6/36

2. Symbian C++简介
首先还是来了解一下什么是 Symbian C++吧。 Symbian OS是Symbian公司专为移动电话设备开发的操作系统。这是当前 占市场份额最大的手机操作系统。Symbian公司最大控股公司就是Nokia。所以 要更加详细地了解Symbian C++,Symbian官方网站和Nokia论坛都会是一个不错 的地方。 Symbian C++是 Symbian OS 最基本的编程语言。 “最基本”这三个字往往 具有很大的魅力——它意味着更纯粹的功能和更高效的表现。Symbian C++是改 进后的 C++。之所以改进是为了使 C++更适于在手机这个受限设备中施展舞 技。手机设备的突出特点是资源宝贵,为此,我们不得不为 C++这位优秀的舞 者套上脚镣。至于 Symbian C++与普通 C++具体有何不同,我将在“Symbian C++独特机制”中详细说明。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

7/36

3. Symbian C++开发环境搭建
工欲善其事,必先利其器。我们首要处理的是开发环境的搭建。而对于手 机程序开发来说,由于开发机与运行机迥然不同,致使开发环境的搭建略显麻 烦。 Nokia 为我们提供了两种开发环境搭建方案,分别基于 Microsoft Visual Studio IDE 和 Eclipse IDE。而在介绍这两种方案之前,我想先简单介绍一下 Nokia 的“Carbide” 。因为在下面的内容里,处处都会有它的身影闪现。

3.1. Nokia的Carbide
Carbide 是 Nokia 推出的新一代移动开发工具。Carbide 不仅仅是一个新名 字,它实质上代表着 Nokia 为了将其开发工具融入一个共通框架而采取的深思 熟虑的举措。 Carbide 使移动开发在功能和效率上迈向一个新高度。它的出现意味着开发 者拥有了一个可以在多种平台下用多种语言进行开发的开发软件家族。 Carbide 基于开放的 Eclipse 框架,因之能够利用其它的 Eclipse 插件和产品 实现扩展。 Carbide 工具集中于三个主要的开发领域,如下所述。

3.1.1.

针对JAVA的Carbide开发工具

由于针对移动 Java 开发的开源或免费工具纷纷涌现,Carbide 在该领域已 无发展必要。基于此,Nokia 论坛(Forum Nokia)将 Carbide.j 撤回。Nokia 论 坛遵守其承诺,会继续为开发者提供移动 Java 开发相关的 SDK 和设备相关 (device-specific)工具。

3.1.2.

针对Symbian OS C++的Carbide开发工具

在该领域,Nokia 推出了 Carbide.c++和 Carbide.vs。 Carbide.c++是基于 Eclipse 的开发工具家族,它支持 S60 平台、Series 80 平台、UIQ 和 MOAP 的 Symbian OS C++开发。Carbide.c++家族包含以下四个 版本: Carbide.c++ Express(EXP) :提供针对 SDK 基本的编译调试工具 (项目输入、类浏览等) 。该版本针对入门级开发人员和学术研究者。 Carbide.c++ Developer Edition(DEV) :除提供 EXP 功能外,还提供 设备关联(on-device)调试和图形 UI 设计功能。该版本针对创建高级 系统、中间件和应用软件的开发人员。 Carbide.c++ Professional Edition(PRO) :除提供 DEV 功能外,还提

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

8/36

供产品和手机研发的执行工具。该版本针对做产前设备相关工作的开 发人员。 Carbide.c++ OEM Edition(OEM) :除提供 PRO 功能外,还提供诸如 ROM 和 JTAG 支持的手机制造工具。该版本针对设备制造者。 在这四个版本中,除了 EXP 版本是免费产品外,其它版本均为收费产品。 与 Carbide.c++不同,Carbide.vs 并不是一个独立的 IDE,而只是一个插 件。它能够使 Visual Studio 用户开发适用于 Symbian OS 平台(包括 S60 平台和 Series 80 平台)的 C++代码。 Carbide.vs 是 Visual Studio 插件,并不基于 Eclipse。Carbide.vs 2.0 适用于 Visual Studio 2003,Carbide.vs 3.0 适用于 Visual Studio 2005。

3.1.3.

实现用户界面个性化和定制化的Carbide工具

Carbide.ui 是图形化的所见即所得的工具家族,支持基于 S60 平台和 Series 40 平台移动设备的界面定制。该家族的第一款产品就是 Carbide.ui S60 Theme Edition for Symbian OS。

3.2. 基于Microsoft Visual Studio IDE的开发环境 搭建
Nokia 为了使开发人员可以在熟悉的 Visual Studio IDE 环境下开发 Symbian C++项目,推出了工具组件 Carbide.vs。 如果您长期工作于 Visual Studio IDE 下,那么该方案无疑是您的首选。令 人欣喜的是,就在我写这份文档期间,Nokia 已经推出了适用于 Visual Studio 2005 的 Carbide.vs 3.0。在此之前,Carbide.vs 仅支持 Visual Studio 2003,这是 令很多开发者颇感郁闷的一件事情。 为了写好这篇文档,也为一品刚出炉的 Carbide.vs 3.0,我特别使用该方案 进行了开发环境的搭建,以下是详细的搭建过程。

3.2.1.

安装Carbide.vs 3.0 的必要条件

Microsoft Windows XP Pro SP2 或 Windows Vista Microsoft Visual Studio .NET 2005 SP1,包含 J# runtime environment Java runtime 1.5 或更高版本 至少一个被支持的 Symbian OS SDK Nokia PCSuite 6.7 或更高版本 ActivePearl,选择能够满足 SDK 应用的版本,推荐版本为 5.6.1.X

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

9/36

3.2.2.

安装Visual Studio 2005

IDE 当 然 是 首 先 要 装 的 了 。 值 得 注 意 的 是 , 安 装 要 包 含 J# runtime environment。至于 SP1,并不必须。但 Nokia 强烈建议安装 SP1,最好还是安 装(要做好心理准备,SP1 的安装时间甚至可能超出 Visual Studio 本身的安装 时间) 。 如果您的Visual Studio没有包含J# runtime environment,可以到微软网站下 载“Visual J# Redistributable Packages”进行安装。 如果您没有打SP1 补丁,可以到微软网站下载“Visual Studio 2005 Service Pack 1 (SP1)”进行补丁安装。

3.2.3.

安装JRE和ActivePerl

如果您的计算机还没有JRE,那就要到SUN网站下载安装了。JRE选择最新 版本即可。 之 后 就 要 安 装 ActivePerl 。 Nokia 推 荐 5.6.1.X 版 本 , 我 们 下 载 ActivePerl 5.6.1.638 就可以了。ActiveState网站提供它的免费下载。

3.2.4.

选择安装SDK

进行 Symbian C++的开发,重要的是选择合适的 SDK。 首先说明一下 SDK 与手机平台之间的关系。事实上,Symbian 操作系统并 不像 Windows 操作系统那样,对用户界面做详细设计(这个从实现角度来说是 不现实的,另一方面,手机厂商们大概也不愿意共用一套 UI) 。除此之外,不 同版本的手机在基本功能上也是各有千秋、大相径庭。那么为了实现不同手机 的软件扩充,手机厂商就在 Symbian OS 的基础上构建了适应不同手机的开发平 台(有人将手机开发平台,如 S60 平台,误认为手机的操作系统,这未免主观 臆断) 。这些开发平台都会向手机软件开发者提供 SDK,最终形成了开发平台 与 SDK 间的一一对应,我们也就用 SDK 的名称称呼与其对应的开发平台。实 际上,对于开发者来说,完全可以将二者杂作一谈。 目前,Symbian 的开发平台主要为 S60、Series 80、Series 90(Nokia 的 Series 40 及其之前版本并未使用 Symbian OS) 、UIQ。 这几个平台相应的手机是比较好区分的。 S60 平台基本定位于单手操纵设备,是典型的大众平台。这也正是 S60 系 列在手机市场中占主导地位的原因所在。具体看来,S60 手机机身轻巧,屏幕 分辨率从 176*208 像素到 416*352 像素共涵盖 6 种规格,五方向键,两功能 键,菜单一般呈九宫方式排列。 Series 80 平台则是高端商务手机平台,代表着 Nokia 最强的技术。具体看 来,S80 手机机身失之轻巧,铅笔盒式的构造,外部为标准手机操作界面,横 向打开,内部为 640*200 大屏幕,四功能键,若干快捷键和完整 QWERTY 键 盘。 Series 90 则使用 640*320 大屏幕,最显著的特征就是除少量按键外全部触

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

10/36

摸屏控制。 UIQ 平台不属于 Nokia 的 Series 系列,是由 Symbian 的 UIQ 技术公司 (UIQ Technolgy)提供的,也是趋于高端的平台,有显著的多媒体性,功能全 面,可支持手写。 从现在看来,S60 平台占有的市场份额最大(所以您若还未确定开发平 台,S60 是一个比较好的选择) 。其余平台,也仅 UIQ 可以稍与之抗衡,但据预 测,UIQ 拥有不错的前景。值得一提的是,Nokia 似乎放弃了 Series 90 平台, 在其开发者论坛中已寻觅不到 Series 90 的踪影。 现在,您应该了解到手机的 SDK 与其版本间的密切关系了。所以,进行手 机开发,首要确定您的开发产品要在哪个版本的手机上运行,也即首要确定一 款用于开发的 SDK。 如果您不清楚手机对应的开发平台,就到该手机厂商的官方网站上查询。 Nokia手机可以在Nokia论坛的“终端规范”中查询。 S60 平台的SDK可以在Nokia论坛的“S60 Platform SDKs for Symbian OS, for C++”中选择下载。值得注意的是,S60 的每个平台都提供两套SDK,分别 针对C++和Java,所以一定要分辨清楚。一般针对C++的,会有“for C++”的字 样,而针对Java的则有“for Java”的字样。 Series 80 平台的SDK可以在Nokia论坛的“Series 80 Platform 2.0 SDK for Symbian OS”中选择下载。 UIQ平台的SDK可以在UIQ Technology的“SDK Download”中选择下载。

3.2.5.

安装Carbide.vs

Carbide.vs在Nokia论坛的“Carbide.vs 3.0”中下载。 下载后就可以安装了。Carbide.vs 的 Installshield 做得颇为人性化。如果您 没有安装必要的或需要的相关软件,Carbide.vs 的 Installshield 就会显示 Missing prerequisites 页 面 进 行 提 示 , 并 给 出 下 载 地 址 。 所 以 您 完 全 可 以 直 接 安 装 Carbide.vs,在它的提示下进行相关软件的安装。

3.2.6.

安装完成

到此为止,我们的开发环境已安装完毕。下面来检验一下成果。 打开 Visual Studio 2005,选择菜单“File -> New -> Project”以打开“New Project”对话框。如果没有意外的话,您会发现在“Project types”版块的树形 列表中新增添了选项“Visual C++ -> Symbian” 。 于“Project types”版块选择“Visual C++ -> Symbian” ,于“Templates”版 块选择“New Symbian OS Project” ,继而在对话框下方为新的项目命名设址, 最后点击确认按钮。 在安装后首次运行,会弹出“Enable/Disable SDKs”对话框。在这里,您 可以激活已安装的 SDK。只有在这里被激活的 SDK,才能在之后的应用中出 现。选择之后点击确认按钮继续。 之后进入“Create New Symbian OS Project”向导对话框。按照向导为新项 目设 定诸如项目类型、项目模板、SDK 等属性。为便于测试,项目模板选择

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

11/36

“Hello World Application” 。项目设置完毕,点击完成按钮。 进 入 IDE 界 面 , 系 统 已 自 动 生 成 程 序 。 选 择 菜 单 “ Build -> Build Solution”进行编译,选择菜单“Debug -> Start Debuging”进行调试。此时 IDE 会调用仿真器调试程序。如果进行到这一步,您的安装就算成功了。

3.3. 基于Eclipse IDE的开发环境搭建
如果您对 Eclipse 风格青睐有加,则可以选择 Nokia 提供的 Carbide.c++。 Carbide.c++是 Nokia 以 Eclipse 为基础开发的针对 Symbian C++编程的 IDE,所 以 您 不 必 特 意 为 此 提 供 一 个 Eclipse 。 唯 一 遗 憾 的 是 Carbide.c++ 所 基 于 的 Eclipse 版本似乎较低,并不支持 Eclipse 的一些新的辅助功能。 由于做项目时 Carbide.vs 未能支持 VS2005,所以我选择了这一方案。 开发环境的搭建要分别安装 JRE、ActivePerl、SDK 和 Carbide.c++。是否 需要按照顺序安装,尚不清楚。但我按照以上列举的先后顺序安装未出任何问 题。从它们之间的关系来说,这也是一种比较合理的安装顺序。另一个问题是 是否需要将以上内容安装在一个逻辑盘上。这个是不需要的,但为什么不呢? 它们本身就是紧密联系的,何必要将其分开呢? JRE 、 ActivePerl 、 SDK 的 安 装 详 见 3.2 节 。 Carbide.c++ 在 Nokia 论 坛 的 “Carbide Development Tools for Symbian OS C++”中下载。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

12/36

4. Symbian C++独特机制
Symbian C++为了适应手机应用,一方面,在基础规定上,对标准 C++做 了一些调整;另一方面,在高层实现上,形成一些自己的风格。Symbian C++的 这些特点很可能让您不知所措。下面我对其主要的特点作一简单介绍。

4.1. 命名惯例
Symbian C++有一套自己的命名规范。这些规范不仅使程序风格井然,更为 程序员开发浏览程序提供必要的信息。

4.1.1.

命名总则

始终使用有意义且慎重考虑的名称,避免使用数字或字母等含义模糊 的元素。 名称中的不同单词直接相连,避免使用“_”等连接符,除命名首字母 外单词首字母大写。 尽量避免单词缩写,所采用单词缩写要始终保持一致。公认缩写(如 “SQL” )仅保留首字母的大写(如“SQL”在命名中写作“Sql”。 ) 函数名、类名、结构类型名、常量名和枚举名首字母大写,其余命名 首字母小写。 命名严格遵循 Symbian C++约定成俗的命名前缀和命名后缀。

4.1.2.

命名前缀与命名后缀

前缀 C:类命名前缀,表示该类是继承于某个 Cbase 基类的堆分配 类。 前缀 R:类命名前缀,表示该类是含有在其他地方维护的某个真实资 源句柄的资源类。 前缀 T:类命名前缀,表示该类是不拥有任何外部对象的值类或类 型。 前缀 M:类命名前缀,表示该类是定义了一些由继承类实现的抽象协 议定义的接口类。 前缀 E:枚举值命名前缀,表示被命名者为枚举值。枚举类型命名采 用“前缀 T” 。 前缀 K:常量命名前缀,表示被命名者为常量。 前缀 i:成员变量命名前缀,表示该变量为某类或结构类型中的成员。 前缀 a:函数参数命名前缀,表示被命名者为函数参数。 后缀 L:函数命名后缀,表示该函数可能发生 Leave。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

13/36

后缀 C:函数命名后缀,表示该函数会将被处理对象压入清除栈。 后缀 D:函数命名后缀,表示该函数会将被处理对象销毁。

4.2. 基本类型
Symbian C++在标准 C++的基础上定义了一套新的类型符号,而原有的类 型符号依然有效。我们在编程过程中应使用新类型符号,不再使用原类型符号 (void 除外) 。 Symbian C++在“Epoc32\include\e32def.h”文件中定义了这些类型符号。 下表是我对其的总结: Symbian C++类型符号
类别 符号 TInt TInt8 TInt16 整型 TInt32 TUInt TUInt8 TUInt16 TUInt32 定义 typedef signed int TInt; typedef unsigned char TUint8; typedef short int TInt16; typedef long int TInt32; typedef unsigned int TUint; typedef unsigned char TUint8; typedef unsigned short int TUint16; typedef unsigned long int TUint32; #if defined(_UNICODE) typedef TText16 TText; #else typedef TText8 TText; typedef unsigned char TText8; typedef unsigned short int TText16; 解释 用于一般的整数运算。 TInt 的扩展,用于大小非常重要 的情况。自上到下依次为 8 位、 16 位和 32 位整型。 无符号整型。 TUInt 的扩展,用于宽度非常重 要的情况。 自上到下依 次为 8 位、16 位和 32 位无符号整型。 用于表示字符。宽度取决于 EPOC 编译,Unicode 编译下为 16 比特,非 Unicode 编译下为 8 比特。 独立于编译的 8 比特字符。 独立于编译的 16 比特字符。 值可能为 true 或 false 的布尔 型。在 Symbian C++中用枚举值 ETrue 表 示 true , EFalse 表 示 false。 64 位浮点型,优先考虑使用。 32 位浮点型,运算快捷但精度 不高,用于空间或时间非常宝贵 的情况。 同 TReal。 仅适用于无类型指针定义,其它 情况仍推荐使用 void。

TText 文本型 TText8 TText16

布尔型

TBool

typedef int TBool;

TReal 浮点型 TReal32 TReal64 空类型 TAny

typedef double TReal; typedef float TReal32; typedef double TReal64; typedef void TAny;

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

14/36

4.3. 类的划分
Symbian C++将 C++的类分为六类。不同的类在创建、使用、撤销等方面 都有明显的区别。下面对它们进行简单的介绍。

4.3.1.

C-Class:堆分配类

在 Symbian C++中,C-Class 类是最主要的一种类。它们以“C”作为类名 前缀,建立于堆上,用指针标识自身。 C-Class 类必须继承自 CBase 类,CBase 类提供了一个虚拟析构函数和四个 运算符 new 重载函数。 CBase 的虚拟析构函数保证了当销毁某个 C-Class 类的对象时调用适当的析 构函数。 在 CBase 的四个运算符 new 重载函数中,我们经常使用的函数是:
TAny* operator new(TUint aSize,TLeave aLeave);

在很多地方,您都会发现“new(ELeave)”这样古怪的 new 运算符,以上的 函数就是它的定义。 这里要说明的是,在 Symbian C++中,我们一般都用“new(ELeave)”代替 “new”的使用。这样做的原因是改良后的 new 运算符新添了两点重要的功 能: 如果在为类实例化时系统内存耗尽,触发异常退出。在创建对象失败 的情况下触发异常退出,这是由 Symbian C++的异常处理机制决定的。 将新建对象的所有内容设定为二进制零。该功能保证创建后的对象可 以处在一个相对安全的状态下。有了这样的功能,我们就不必在类的 构造函数中为其成员变量赋 0(NULL)值了。 如果 C-Class 类对象用作自动变量,需要将其在使用前压入清除栈,使用 后弹出清除栈;如果 C-Class 类对象用作成员变量,需要在其拥有类的析构函 数中将其 delete。

4.3.2.

R-Class:资源类

R-Class 类是较为复杂的一种类。它们以“R”作为类名前缀,一般建立于 栈结构上。R-Class 的突出特点是内部包含资源。与之适应的是,它们都有针对 资源的清除函数 Close()。 虽然 R-Class 类对象本身并不分配到堆上,但它们都包含有资源,所以依 然存在清除问题。 如果 R-Class 类对象用作自动变量,需要将其在使用前压入清除栈,使用 后弹出清除栈;如果 R-Class 类对象用作成员变量,需要在其拥有类的析构函 数中调用其清除函数,一般为 Close(),进行清除。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

15/36

4.3.3.

T-Class:值类

T-Class 类是相对简单的一种类。它们以“T”作为类名前缀,一般建立于 栈结构上。T-Class 类有可能是对具有相同用途的数值的封装,也可能是对具有 相同用途的方法的封装。总之,它们自身不占有资源,也不包含外部资源,不 需要对其作专门的清除工作。

4.3.4.

M-Class:接口类

M-Class 类是用于功能扩展的接口。它们以“M”作为类名前缀。M-Class 类由一个或多个纯虚函数组成且没有成员数据,因此它们不能被实例化。一 般,M-Class 用于类的多重继承中,使类具有某些特殊的属性。 标准 C++多重继承的语法允许不必要的复杂继承模式,Symbian C++则用 惯例限制了这些模式。Symbian C++规定 C-Class 类只能继承自一个 C-Class, 对于类功能的扩展,就依赖于 M-Class 类。一个 C-Class 类被允许继承自另一个 C-Class 类和零个以上的 M-Class。

4.3.5.

静态类

在 Symbian C++中有一种特殊的类,它们仅具有静态成员。这种类就是静 态类。静态类类名不使用类前缀,其使用也不需要实例化,如经常接触到的 User 类。

4.3.6.

D-Class

D-Class 类是内核认知的驱动程序类,类名使用类前缀“D” 。该类我没有 接触到,具体情况并不清楚。

4.4. 异常处理
手机设备的突出特点是资源紧缺。因此,在程序运行时由于资源不足引起 的异常就更需妥善处理。由于历史原因和效率方面的考虑,Symbian C++并未采 用标准 C++的 try-catch-throw 异常处理方式,而是设计了一套不同的异常处理 机制。 Symbian C++的异常处理是这样实现的: TRAP 和 TRAPD 宏允许在某个异常陷阱工具中运行代码,相当于标准 C++中的 try-catch。 User::Leave()及其扩展函数负责异常的抛出,相当于标准 C++中的 throw。 Symbian C++中的异常与标准 C++中的类似,它们并不抛出一个对象,而

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

16/36

是一个 32 位的出错代码。

4.4.1.

TRAP和TRAPD

TRAP 和 TRAPD 是 Symbian C++提供的异常捕获模块(trap harness)宏。 它们的作用是完全相同的。当 TRAP 和 TRAPD 包含的异常退出代码发生异常 时,程序会立即回到该宏处进行处理,并返回错误代码。 您可以按照如下方式使用 TRAP:
TInt error; TRAP(error,doExampleL()); if(error!=KerrNone) { //Do some error code }

而 TRAPD 相较 TRAP 的区别仅在于,TRAPD 宏包含了错误代码接收变量 的定义,更便于您使用。您可以按照如下方式使用 TRAPD:
TRAPD(error,doExampleL()); if(error!=KerrNone) { //Do some error code }

不过需要说明的是,当编制标准的 Symbian OS 应用时,您并不需要去捕获 每个异常,因为框架已在适当位置实现了异常捕获和相应的处理代码。我们在 普通的编码中并不使用 TRAP 和 TRAPD。

4.4.2.

异常抛出函数

我们如何抛出异常,前面已经提到 User::Leave()函数,下面对其及其扩展 函数进行详细说明。

4.4.2.1. User类简介
User 类是提供系统静态函数(System Static Function)的类。这些函数涉及 到许多系统元件 API(Symtem component APIs) 。 User 类中的多数函数都涉及到当前线程或者它的堆。比如 User::Exit()导致 当前线程终止,User::Alloc()则在当前线程的堆中分配内存。 之所以在本文中提到 User 类,是因为它包含了 Cleanup 支持函数。而异常

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

17/36

抛出函数就隶属于 Cleanup 支持函数。您在下文会了解到“Cleanup”在整个异 常处理机制中的重要作用。 下面要介绍的异常抛出函数 Leave()、LeaveNoMemory()、LeaveIfError()和 LeaveIfNull()都是 User 中的系统静态函数。

4.4.2.2. User::Leave()函数
该函数的函数原型为:
static IMPORT_C void Leave(TInt aReason);

该函数将导致程序回溯到最近的异常捕获模块,并将异常代码 aReason 传 递给异常捕获模块。

4.4.2.3. User:: LeaveNoMemory()
该函数的函数原型为:
static IMPORT_C void LeaveNoMemory();

该函数将导致程序回溯到最近的异常捕获模块,并将异常代码 KerrNoMemory 传递给异常捕获模块。

4.4.2.4. User:: LeaveIfError()
该函数的函数原型为:
static IMPORT_C TInt LeaveIfError(TInt aReason);

如果 aReason 为负数,该函数将导致程序回溯到最近的异常捕获模块,并 将异常代码 aReason 传递给异常捕获模块; 如果 aReason 为非负数,该函数仅返回 aReason。

4.4.2.5. User:: LeaveIfNull()
该函数的函数原型为:
static IMPORT_C TAny *LeaveIfNull(TAny *aPtr);

如果 aPtr 为 NULL,该函数将导致程序回溯到最近的异常捕获模块,并将 异常代码 KerrNoMemory 传递给异常捕获模块;

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

18/36

如果 aPtr 不为 NULL,该函数仅返回 aPtr。

4.4.3.

可能异常退出的操作符:new(ELeave)

在 Symbian OS 中,由于内存不足而导致的 new 操作失败现象可能经常发 生。介于此,Symbian C++重载了 new 操作符,为其增加了一个枚举常量参数 ELeave,形成操作符“new(ELeave)” 。 new(ELeave)的用法和 new 完全一样,只是当 new 操作失败时会引起异常 退出。 在 Symbian C++中,我们用“new(ELeave)”来替代“new” 。

4.4.4.

可能异常退出的函数

上面介绍了引起异常退出的因素。如果您的代码包含异常退出因素,那么 您就不得不对其作特殊处理(比如,如果发生异常退出,怎样使程序不会发生 内存泄露) 。现在的问题是,如何才能判断代码是否可能发生异常退出。 Symbian C++的解决方案是依靠以下的编码惯例:总是在可能发生异常的 那些函数名称后添加后缀“L” 。 这样做的前提是,我们需要鉴别出我们设计的函数是否是可能异常退出的 函数。 一个函数如果包含了以下代码之一,我们就认为它为可能异常退出函数: 包含异常抛出函数; 包含“new(ELeave)”操作符; 包含可能异常退出函数。 如下面的函数,它的每一行都使该函数成为一个可能异常退出函数:
void MyFunctionL() { iMember=new(ELeave) CMember; iValue=AnotherFunctionL(); User::LeaveIfError(iSession.Connect()); }

4.4.5.

引入清除栈(Cleanup Stack)机制

让我们再审视一下上文所介绍的异常处理机制。 根据上文所说,如果一个函数产生异常,程序会回溯到异常捕获模块。这 意味着在这之间的所有函数所产生的自动变量都被删除了。如果这些自动变量 包含有指针,而这些指针通常会指向一个内存空间,这时就发生了比较严重的 问题:内存泄露。 Symbian C++的解决办法是引入清除栈机制。Symbian C++的异常处理只有

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

19/36

在清除栈的支持下才能正常实施,所以您也可以认为清除栈是 Symbian C++异 常处理机制的一部分。下面我将对其进行详细介绍。

4.5. 清除栈
清除栈是一个栈管理结构。它用来保存那些需要在发生异常后释放资源的 对象指针。这样,在发生异常后,异常处理机制就可以通过清除栈实现对失效 内存的释放。

4.5.1.

清除栈成员要求

我们要将什么样的变量加入清除栈,弄清这一点是很重要的。 需加入清除栈的变量要符合以下要求: 1. 该变量为自动变量,不为成员变量; 2. 该变量拥有内存资源; 3. 在该变量的生存期内有可能发生异常退出。 首先说明条件 1。为什么不能是成员变量?Symbian C++实际上存在两种清 除机制,一种是清除栈,另一种就是类的析构函数。这两种机制各有分工,并 行不悖。Symbian C++严格规定,我们要在析构函数中对成员对象进行必要的清 除处理。在发生异常后,成员变量的清除工作就由析构函数处理。如果又将成 员变量加入清除栈,则该变量就会被清除两次。 条件 2 要求变量拥有内存资源,那么什么样的变量拥有内存资源呢?如上 所述,Symbian C++的类分为四种:C-Class、R-Class、T-Class 和 M-Class。其 中 M-Class 作为接口类,一般不能实例化,不用考虑。T-Class 是值类,不具有 资源。剩下的 C-Class 和 R-Class 都是拥有内存资源的类。其中 C-Class 是堆分 配类,本身占有内存,R-Class 则包含占用内存的资源。 而条件 3 在实际处理中通常不做考虑,因为很难判断变量是否满足它。

4.5.2.

清除栈的操作

清除栈的操作主要分为两种,分别为压入操作和弹出操作。清除栈操作看 来较为简单,但具体来讲,还是有一定复杂性的。 类 CleanupStack 是 提 供 清 除 栈 操 作 的 静 态 函 数 集 合 类 。 我 们 用 CleanupStack::PushL()函数进行栈的压入操作,用 CleanupStack::Pop()函数进行 栈的弹出操作,如果想弹出后立即销毁对象,可以选择使用 CleanupStack::PopAndDestroy()函数。这些是基本的操作函数,其中弹出操作普 遍适用,而压入操作则仅对创建于堆上的变量适用,如 C-Class 对象。对于较 为复杂的 R-Class 对象或有特殊需求的对象,Symbian C++亦提供了相应的压入 操作函数或机制。下面针对不同的变量,介绍清除栈的操作。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

20/36

4.5.2.1. C-Class对象的清除栈操作
C-Class 对 象 直 接 建 立 于 堆 上 , 其 清 除 栈 操 作 比 较 简 单 , 直 接 使 用 CleanupStack 类提供的压入弹出函数就可以了。当发生异常退出后,异常处理 机制会对该对象指针进行 delete 操作。示例代码如下:
CObject* object = CObject::NewL(); CleanupStack::PushL(object); object->LeavingFunctionL(); CleanupStack::PopAndDestroy(object);

4.5.2.2. R-Classs对象的清除栈操作
R-Class 类的一个特点是具有资源清除函数,如 Close(),负责清除其拥有 的资源。所以,对于 R-Class 对象的清除,关键是调用其资源清除函数清除其 资源。对此,Symbian C++专门提供了 CleanupClosePushL()函数,该函数定义 于“epoc32\include\e32base.h” 。示例代码如下:
RObject object; object.Open(); CleanupClosePushL(object); object.LeavingFunctionL(); CleanupStack::PopAndDestroy(&object);

4.5.2.3. 特殊的R-Class对象清除栈操作
以上的方法并不适用于所有的 R-Class 对象。例如您可能会广泛使用的指 针动态数组类 RPointerArray,它的资源依然是指针。对它的清除就要首先调用 函数 RPointerArray:: ResetAndDestroy(),清除指针资源所拥有的内存,再调用 RPointerArray::Close()函数。像这样的对象如何压入清除栈呢?Symbian C++提 供 了 函 数 CleanupResetAndDestroyPushL() 实 现 对 其 的 压 入 。 该 函 数 定 义 于 “epoc32\include\mmf\common\mmfcontrollerpluginresolver.h” 。示例代码如下:
RPointerArray object; CleanupResetAndDestroyPushL(object); ... CleanupStack::PopAndDestroy(&object);

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

21/36

4.5.2.4. 具有特殊需求对象的清除栈操作
我们在编程过程中有可能遇到或设计出清除方式与上不同的类,这样的类 该如何压入清除栈呢?Symbian C++为我们提供了 TcleanupItems 类。该类将欲 清除对象与其清除函数绑定,使得异常处理机制能够调用其清除函数对其进行 清理。其实 4.4.2.2 和 4.4.2.3 都是这种方法的特例。示例代码如下:
//定义该类的文件中 void RObject::ReleaseOnCleanup(TAny* aObject) { reinterpret_cast(aObject)->Release(); } //使用该类的文件中 RObject* object=GetObject(); CleanupStack::PushL(TCleanupItem(ReleaseOnCleanup,object)); iContainer->AddL(object); CleanupStack::Pop(object);

4.5.2.5. TAny*指针的压入
清除栈也支持无类型指针(TAny*或 void*)的压入。如果压入指针无类 型,异常处理机制会调用 User::Free()函数进行处理。

4.5.3.

清除栈弹出操作的debug版本

清除栈操作很容易因程序的复杂而出现 bug。清除栈 bug 由于涉及到指针 的操作,相较其它 bug 更隐藏。为了更有效地提前发现清除栈 bug,清除栈弹 出操作提供了 debug 版本。 普通版本的清除栈弹出函数原型如下所示:
//弹出一个成员 void Pop(); //弹出aCount个成员 void Pop(TInt aCount); //弹出并销毁一个成员 void PopAndDestroy(); //弹出并销毁aCount个成员 void PopAndDestroy(TInt aCount);

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

22/36

与其对应的 debug 版本如下所示:
//弹出一个成员 void Pop(TAny *aExpectedItem); //弹出aCount个成员 void Pop(TInt aCount, TAny *aLastExpectedItem); //弹出并销毁一个成员 void PopAndDestroy(TAny *aExpectedItem); //弹出并销毁aCount个成员 void PopAndDestroy(TInt aCount, TAny *aLastExpectedItem);

我们看到 debug 版本比普通版本多了一个参数 aLastExpectedItem,该参数 为我们预期的最后一个弹出指针。Debug 版本会拿其与真实值进行比较,如果 相同,程序正常执行;如果不同,就会发生 E32USER-CBase 90 panic,程序终 止。这样,我们就能在调试过程中更快发现清除栈 bug。 值得注意的是,弹出函数的 debug 版本只有在程序的 debug 版本中发挥作 用。在程序的 release 版本中,弹出函数的 debug 版本与标准版本的作用相同。

4.5.4.

使用清除栈的注意事项

认清清除栈的本质,不要把清除栈看作垃圾箱,希望添加的内容会在 程序执行最终被清除。 不要把成员变量压入清除栈。 有压入就要有弹出,保证清除栈的压入弹出操作在逻辑上匹配。 清除栈的弹出操作使用 debug 版本,及时发现清除栈 bug。

4.6. 两阶段构造
清除栈机制已经可以保证 Symbian C++的异常处理机制在大多数情况下正 常进行。但是仍有一个地方它无能为力,为此 Symbian C++引入了两阶段构造 机制。

4.6.1.

引入原因

我们用 new(ELeave)操作符实例化一个基于 CBase 的类。这时在该类的构 造函数中会发生一些值得关注的事情。 我们假定这个类需要在构造时申请一些内存(比如它需要初始化它的一个 成员变量,而不巧的是,这个成员变量也是一个基于 CBase 的类的对象) 。 现在让我们开始该类的实例化。首先,程序为该类的实例化申请内存,执 行成功;之后,程序执行该类的构造函数,又要申请内存,但系统内存耗尽, 执行失败。执行失败有两种处理方案,我们分别来分析它们造成的结果: 1. 如果不触发异常退出,则构造函数不能将初始化失败的信息传递出

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

23/36

来,我们接收到的对象指针指向的是一个构造不完全的对象。这将对 之后的程序运行产生不可预知的影响。 2. 如果触发异常退出,则程序回溯到最近的异常处理模块,进行相关的 异常处理。但是我们知道,程序已经为该类的实例化申请了内存,但 该类的实例化指针却没有及时加入到清除栈。那么程序的回溯就造成 了内存泄露。 为了解决这样的问题,Symbian C++引入了两阶段构造机制。

4.6.2.

具体措施

以上问题的主要症结就是类的构造函数可能产生异常。两阶段构造机制的 核心思想就是,使类的构造函数不会产生异常,将那些可能产生异常的初始化 操作从构造函数中抽出,放在一个稍后执行的函数(第二阶段构造函数)中。 这样一来,类的构造实际上就分为两个阶段了。依照惯例,第二阶段构造函数 统一命名为 ConstructL。 我们以类 CMyClass 为例。如果它遵循两阶段构造, 那么要完整地构造 它,就要用到下面的代码:
CMyClass* p=new(ELeave) CMyClass(); CleanupStack::PushL(p); p->ConstructL();

我们看到,创建一个类,原来用一条语句,现在要用三条或四条语句。这 对于类的使用者来说太麻烦了。为了解决这个问题,Symbian C++又为需要两阶 段构造的类添加了两个静态函数:NewL()和 NewLC()。我称呼它们为构造器。 这两个构造器的内容一般都是固定的,NewL()的定义如下:
static CMyClass* CMyClass::NewL() { CMyClass* self=NewLC(); CleanupStack::Pop(); return self; }

NewLC()的定义如下:
static CMyClass* CMyClass::NewLC() { CMyClass* self=new(ELeave) CMyClass(); CleanupStack::PushL(self); self->ConstructL(); return self; }

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

24/36

我们可以从以上定义中看出,用 NewL 构造器构造的对象,没有被压入清 除栈;用 NewLC 构造器构造的对象,已经被压入清除栈。您可以根据具体的 情况选择使用。 为 CMyClass 加入静态函数 NewL()和 NewLC()后,我们再创建它,就可以 用这样的代码:
CMyClass* iMyClass=CMyClass::NewL();

或者:
CMyClass* myClass=CMyClass::NewLC();

4.6.3.

总结

综上所述,一个标准的两阶段构造类包含以下四个构造组件: 1. 标准 C++的构造函数。实际上,Symbian C++已经摒弃了该函数的功 能,建议您将该函数置空。但是,如果您在其中编辑一些不会导致异 常退出的代码,也是可以的。有时这样做会使您的代码更清晰。由于 构造器的出现,构造函数的访问权限通常为 private。 2. 第二阶段构造函数 ConstructL()。Symbian C++建议在其中实现类的所 有初始化工作,它成为构造函数的替代品。当然,它的访问权限通常 也为 private。 3. 构造器 NewL()。为 public 静态函数,外界使用该函数完成类的实例 化。构造出的对象未压入清除栈,一般用于成员对象的构造。 4. 构造器 NewLC()。为 public 静态函数,外界使用该函数完成类的实例 化。构造出的对象被压入清除栈,一般用于动态对象的构造。 值得说明的是,只要保证程序不会出现内存泄露,您完全可以不遵守两阶 段构造机制。即便采用两阶段构造机制,您也可以根据实际情况对两个构造器 进行取舍。但是,如果您能够完全遵守两阶段构造机制,将使您的代码更好理 解。 实际上,NewL()和 NewLC()函数是如此深入人心,以至成为 Symbian C++ 独特的标志。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

25/36

5. S60 第三版程序框架
在这一部分,我首先对 S60 第三版的程序框架做大致说明,之后结合 HelloWorld 程序疏导一遍程序,最后对程序的特殊文件进行说明。

5.1. 框架概述
S60 第三版的程序框架和 MFC 应用框架貌合神离,它基本由以下五部分组 成。 1. Application(应用类) :应用类是应用程序的启动对象,它定义应用程 序的属性,创建文档类。应用类的基类是 CAknApplication。 2. Document(文档类) :文档类用来存储应用程序的永久状态,一个应 用程序必须有一个文档类的实例,尽管它除了加载 AppUi 类似乎没有 什么别的用途。文档类的基类是 CAknDocument。 3. AppUi(应用界面类) :应用界面类负责处理与应用有关的事情,比如 菜单命令。通常没有屏幕显示,它将图形绘制和基于屏幕的交互操作 委派给自己所拥有的视图类,自己则负责处理来自各个视图和引擎的 消息。应用界面类是整个应用程序的核心。应用界面类的基类是 CAknAppUi 或 CAknViewAppUi。 4. View(视图类) :视图类负责在屏幕上显示那些用户可以与之交互的数 据。它将用户发出的命令传递给 AppUi 类进行处理。需要注意的是, 在 S60 的 SDK 中,对视图的称呼,经常使用 container(容器) ,而不 是 View(视图) 。您可以认为它们是等价的。实际上,当视图仅有一个 控件时,我习惯称它为控件;当视图有多个控件时,我习惯称它为容 器。视图类继承自 CCoeControl 类或者 CAknDialog 类。当应用程序被 设计成应用/视图体系结构时,它继承自 CAknView 类。 5. Engine(引擎类) :引擎类封装了应用程序所需要的功能。用户发出的 指令通过 View 类、AppUi 类,最终传至引擎类进行处理。引擎类处理 的结果则需要通过 AppUi 类传递给 View 类,显示给用户。 这 五 部 分 的 关 系 是 这 样 的 : 应 用 程 序 框 架 负 责 创 建 Application , 而 Application 构造 Document,然后 Document 再创建 AppUi,AppUi 创建并拥有 Engine 和 View。

5.2. 框架详解
有了对程序框架的基本了解,我们共同分析一个简单的程序: HelloWorld,以更加清楚地了解 S60 第三版的程序框架。 利用 IDE 生成 HelloWorld 程序,或装载 SDK 附带的 HelloWorld 程序,开 始我们的分析。我使用的 HelloWorld 程序是用 Visual Studio 2005 IDE 生成的。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

26/36

您会发现生成的程序以文件夹的形式分为若干个部分,首先让我们来看看每个 部分的功能、意义。 data 文件夹:包含 rss 和 rls 文件。rss 为资源文件,rls 为资源本地化文 件。 doc 文件夹:看其英文注释,和程序的签名有关,大概是提供版本信息 的吧。 gfx 文件夹:图形文件夹,包含一张 svg 格式的图标。 group 文件夹:包含 bld.inf 文件和 mmp 文件。bld.inf 文件为项目的组 件定义文件,mmp 文件则指定了项目的详细属性。 help 文件夹:包含与程序帮助相关的文件。 inc 文件夹:包含程序的头文件。比较特殊的是 hrh 文件和 pan 文件。 sis 文件夹:包含 pkg 文件。pkg 文件用于制作程序的安装包。 src 文件夹:包含与程序头文件对应的 cpp 文件。 对以上内容有一个大致了解之后,我们来看看程序是如何运行的。

5.2.1.

E32Main()函数:创建应用类对象

理解一个程序,先要找到它的入口。 HelloWorld 的程序入口为 E32Main()函数。该函数位于 HelloWorld.cpp 文件 中。 HelloWorld.cpp 文件中有两个函数,一个是 E32Main()函数,另一个是 NewApplication()函数。其定义如下所示:
LOCAL_C CApaApplication* NewApplication() { return new CHelloWorldApplication; } GLDEF_C TInt E32Main() { return EikStart::RunApplication(NewApplication); }

其中出现两个陌生的符号: “LOCAL_C”和“GLDEF_C” 。在 e32def.h 文 件中有它们的定义:
#define LOCAL_C static #define GLDEF_C

在 E32Main()函数中调用了静态类 EikStart 中的 RunApplication 函数,参数 即为 NewApplication()函数的函数指针。 EikStart 类仅包含一个静态函数 RunApplication(),负责初始化并运行应用 程序框架。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

27/36

在 E32Main()函数中,将 NewApplication()函数指针传给了框架。框架在适 当时间调用该函数。 NewApplication()函数负责实例化应用类 CHelloWorldApplication,并将其 指针返回给框架。 于是,框架获得应用类对象指针,得以开展进一步工作。

5.2.2.

应用类:创建文档类对象

应 用 类 CHelloWorldApplication 包 含 两 个 函 数 : AppDllUid() 和 CreateDocumentL()。如下所示:
TUid CHelloWorldApplication::AppDllUid() const { return KUidHelloWorldApp; } CApaDocument* CHelloWorldApplication::CreateDocumentL() { return(static_cast<CApaDocument*>(CHelloWorldDocument::NewL(*this))); }

AppDllUid()函数返回应用程序的 UID。那么什么是 UID 呢? UID 也被叫做 GUID,指全球唯一标识符(Globally Unique IDentifier) 。它 由 32bit 数字组成。在 Symbian OS 中,通过 UID 类型(UID Type,被封装于结 构 TUidType 中)标识对象。UID 类型具有 3 个组件 UID,分别为 UID1、UID2 和 UID3。一般情况下,我们所说的 UID 指 UID3。AppDllUid()函数返回的就是 UID3。 UID1 是一个系统级标识符,确定文件的大体属性。比如,对于一个文 件,可以通过其 UID1 辨别出该文件是 exe 文件还是 dll 文件。我们可 以用 mmp 文件中的 TARGETTYPE 语句设置 UID1。 UID2 视 UID1 的不同而表示不同的含义。比如,对于 dll 文件,可以 通过其 UID2 辨别出该 dll 是静态 dll 还是动态 dll。 UID3 是一个应用程序级标识符,用于唯一标识应用程序。应用程序的 UID3 值必须不同于其他所有应用程序。只有 Symbian 才可以发布这些 值。到 Symbian 的网站上注册一个账号,就可以在线申请了。在开发 期间可以使用范围在 0x01000000 和 0x0FFFFFFF 之间的 UID。但需要 非常小心,绝对不要发布带有实验 UID 的应用程序。 我们可以通过 mmp 文件中的 TARGETTYPE 语句设置 UID1,UID 语句设 置 UID2 和 UID3。 CreateDocumentL()函数调用文档类 CHelloWorldDocument 的构造器 NewL() 对其进行实例化,并将实例化指针返回给框架。 在上一节中,框架获得了应用类对象的指针。这之后,框架就可以随时调 用 AppDllUid()函数获得程序的唯一标识做检查之用。框架会在适当时间调用

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

28/36

CreateDocumentL()函数,创建文档类对象,并获得其指针。

5.2.3.

文档类:创建UI类对象

文档类严格遵循两阶段构造,有构造器 NewL()和 NewLC()。您可能很奇 怪,为什么应用类并没有遵循 Symbian 的异常处理机制,直接用 new 操作符进 行构造。这是因为异常处理机制是在创建应用类对象后才建立的。 除了构造相关函数,文档类还有一个函数 CreateAppUiL(),其定义如下:
CEikAppUi* CHelloWorldDocument::CreateAppUiL() { return(static_cast<CEikAppUi*>(new(ELeave)CHelloWorldAppUi)); }

CreateAppUiL()用于实例化 UI 类,并将其指针返回给框架。 在上一节中,框架获得了文档类对象指针在适当的时间,框架会调用函数 CreateAppUiL()创建 UI 类对象,并获得其指针。

5.2.4.

UI类:程序运行中枢

程序进行到 UI 类对象的创建,也就进入我们的可控范围之内了。事实上, 前面的应用类、文档类的内容是不需要我们改写的。我们的编写从 UI 类的构造 函数开始。 UI 类的第二阶段构造函数 ConstructL()除了构造 UI 类对象外,主要完成程 序的初始化和启动工作。比如,创建必要的 View 和 Engine。 程序一经启动,就会进入“等待->接收->处理->回应->等待”的处理逻辑循 环中,直到用户关闭程序或程序出现异常。而这全部的循环就依靠 UI 类的组织 和视图引擎类的响应。 UI 类为了要控制 View 和 Engine,一般会保存它们的指针,将它们作为成 员变量,负责它们的清除(在析构函数中清除它们) 。UI 类在创建 View 和 Engine 时,一般也会向它们传递自己的指针(一般是接口类型指针) ,以使它们 能够与己取得联系。 除了构造析构相关函数外,UI 类中还有以下函数。 BaseConstructL() 函 数 : 该 函 数 用 于 初 始 化 UI 类 对 象 。 一 般 在 ConstructL()函数中首先被调用。 HandleCommandL()函数:该函数用于处理用户命令。当用户出发命 令,框架会自动调用该函数。我们要做的是对该函数进行覆写,使其 能够针对不同的用户命令给予响应处理。 HandleStatusPaneSizeChange()函数:该函数用于处理状态窗格改变事 件。一般情况下,您要在其中对 UI 类所拥有的视图的尺寸做相应调 整。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

29/36

5.2.5.

视图类:程序的前台

视图类是程序与用户间的接口。一个好的视图使程序的易用性大大提高。 一个视图可能包含一个控件,也可能包含多个控件。一般的处理方法是让 视图类继承自 CCoeControl 类,而将各个控件作为视图的成员变量(这里我指 的是传统的基于视图定制的模式。Symbian 的程序组织结构有三种模式,不同 模式间差别还是较大的) 。这种处理方法导致视图成为一个复合控件,即使它仅 包含一个控件。复合控件在很多场合下依然可以被当作一个普通控件来处理, 复合只是它内部的事情。 UI 类对象在实例化视图类时,需要为它设置窗口尺寸,所以视图类的构造 器一般都会有描述尺寸信息的参数。视图类的第二阶段构造函数 ConstructL()负 责视图类的具体初始化工作。以下是 ConstructL()函数的定义:
void CHelloWorldAppView::ConstructL(const TRect& aRect) { CreateWindowL(); SetRect(aRect); ActivateL(); }

其中的三个函数功能如下: CreateWindowL():该函数为控件创建窗口,一般视图的 ConstructL() 首先调用该函数。 SetRect():该函数设定控件的尺寸,尺寸信息来源于 UI 类对象的指 定。 ActivateL():该函数激活控件。每个控件都有一个标志显示它是否被 激活。为什么要这样做呢?因为控件被创建后不一定准备好被绘制 (例如它还没有被设置尺寸) ,如果没有这个标志,框架就不清楚是否 应该去绘制它。一般情况下在控件已做完初始化工作后,就调用该函 数激活它。对于复合控件也不用去激活每个控件,而仅调用视图的 ActivateL()函数就可以了。 除了上面的函数外,视图还有以下的函数经常被用到。 Draw():绘制函数,您可以覆写该函数,定制屏幕绘制动作。但该函 数 不 能 直 接 被 调 用 , 您 可 以 用 DrawNow() 函 数 来 使 框 架 立 即 调 用 Draw()函数。 SizeChanged():处理视图尺寸和位置改变事件。当视图尺位发生变 化,该函数被调用。您可以覆写该函数,设定针对性的处理动作。 CountComponentControls() : 返 回 视 图 包 含 的 复 合 控 件 的 个 数 , 与 ComponentControl()结合使用。这两个函数是复合控件必须具备的覆写 函数。框架处理复合控件时会调用它们。比如 ActivateL()函数就是通 过这两个函数将视图的所有控件一一激活的。 ComponentControl():返回指定索引所对应的控件指针。框架通过 CountComponentControls()函数获得视图所拥有的控件个数,之后就通

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

30/36

过该函数一一获得控件进行处理。控件的索引号从 0 开始。 OfferKeyEventL():处理按键事件。该函数被框架调用的前提是,您 必须通过 UI 类的 AddToStackL()函数将视图添加到控件栈中。只有这 样 UI 类对象才会通过该函数将按键信息传递给视图(后进栈的视图将 先被传递) 。该函数的返回值有两种,分别为 EkeyWasNotConsumed 和 EkeyWasConsumed。当返回 EkeyWasNotConsumed,则该按键事件将被 传递给控件栈中的下一个控件;当返回 EkeyWasConsumed,按键事件 将不再传递。

5.2.6.

引擎类:程序的后台

正如前面所说,引擎类封装了应用程序所需要的功能。引进引擎类,体现 了 Symbian C++一贯的思想,将功能和界面隔离开。这样做使项目更好维护控 制。 在构造引擎类时,我们一般使其继承 CBase 类,在需要用到活动对象机制 时,使其继承 CActive。它的构造析构完全遵循异常处理机制。通常,我们会在 实例化引擎类时,将 UI 类对象的指针(一般为接口指针)传递给它,以便其能 够更好地和 UI 类对象交流。

5.3. 一些特殊的文件
在 S60 项目中,您会发现一些特殊的文件,它们的扩展名分别为 “inf” 、 “mmp”“pkg”“rss”“rls”“hrh”和“pan” 、 、 、 、 。下面我将一一介绍它们。

5.3.1.

inf文件

每个 Symbian C++项目中都会有一个 bld.inf 文件,它是 Symbian C++项目 的组件定义文件,它的名字总为“bld.inf” 。bldmake 根据该文件定义并创建 abld.bat 和 makefile 文件。 bld.inf 文件由若干部分组成,每部分都有一个头部标识。bld.inf 文件共有 四 个 头 部 标 识 , 分 别 为 : prj_platforms 、 prj_exports 、 prj_testexports 和 prj_mmpfiles。 下面是 bld.inf 文件的一些规则: 每个头部标识可以在文件中多次出现,也可以不出现。 头部标识和它们引导的数据不区分大小写。 行尾的反斜线符号表示下行内容是该行内容的延续。 注释采用 C++注释语法。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

31/36

下面是关于 bld.inf 文件的一个例子:
//输出文件 prj_exports myheader1.h myheader2.h //项目文件 prj_mmpfiles myprj1.mmp myprj2.mmp //用于测试的输出文件 prj_testexports mytestheader1.h //测试程序的项目文件 prj_testmmpfiles mytest1.mmp mytest2.mmp

5.3.2.

mmp文件

mmp 文件为 Symbian C++项目的项目定义文件。它以与平台、编译器无关 的方式指定项目的属性。makmake 工具根据 mmp 文件生成适应于具体平台的 makefile 文件。不过一般情况下,并不直接使用 makmake 工具,在 abld.bat 文 件中有调用它的语句。 下面是 mmp 文件的一些规则: 每个声明占用一行。 注释采用 C++注释语法。 行尾的反斜线符号表示下行内容是该行内容的延续。因此,对于地址 的指定,去掉它的尾部反斜线符号。 mmp 文件的具体语法请参考相关 SDK 文档。

5.3.3.

pkg文件

pkg 文件定义了创建安装文件(sis、sisx 文件)的相关信息。MakeSIS 工具 根据 pkg 文件创建安装文件。 pkg 文件的具体语法请参考相关 SDK 文档。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

32/36

5.3.4.
件。

rss文件

我们可以在程序中通过语句定义界面,但是更简单的方法是使用 rss 文 rss 文件为项目资源文件,用于描述项目使用的界面。rss 文件需要使用 rcomp 节能型编译,生成 rsc 文件。在程序中,您可以通过包含 rsc 文件以使用 在 rss 文件中定义的界面。 rss 文件的具体语法请参考相关 SDK 文档。

5.3.5.

rls文件

rls 文件为资源本地化文件。它用于存放本地化的语言文字。通过 rls 文 件,您可以方便地为程序创建多区域的版本。比如您可以创建两个 rls 文件,一 个用于存放英文文本,一个用于存放中文文本。 值得一提的是,用 Carbide.c++生成的程序,rls 文件中的资源本地化字符串 是用 C++的预编译命令“#define”实现的。而用 Visual Studio 2005 生成的程 序,rls 文件中的资源本地化字符串是用“rls_string”系列符号引导的。 rls 文件的具体语法请参考相关 SDK 文档。

5.3.6.

hrh文件

hrh 文件为公共头文件。该文件被 cpp 文件和 rss 文件共享。一般,我们会 在该文件中,用枚举类型定义命令、ID 等,例如菜单命令、按钮命令、控件标 识等。因为这些命令或标识既要在 cpp 文件中使用,又要在 rss 文件中使用,所 以被定义在 hrh 文件中。

5.3.7.

pan文件

pan 文件用于定义 panic 枚举值和 panic 函数。panics 是一种无法被捕捉的 严重提示,它总是导致其所在线程的全部进程的中断,您可以通过调用 User::Panic 函数触发 panics。当程序出现 panics,表明程序在设计上存在问题。 一个合格的程序是不应该出现 panics 的。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

33/36

6. Symbian C++程序安装
如何将编好的程序安装到手机上,这是个不大不小的问题。这一节,我们 专门解决这个问题。

6.1. 在Carbide.c++ v1.2 下制作安装包
具体步骤如下: 1. 点击工具栏中“小锤”图标的下箭头,在弹出菜单中选择“Phone Release”选项进行程序构建。或者选择菜单“Project / Active Build Configuration / Phone Release” ,进行构建版本的设置,之后再选择菜单 “Project / Build Project”进行构建。 2. 在 IDE 中打开文件“<MyApp>\sis\<MyApp>_S60_3_X_v_1_0_0.pkg” (该文件为 IDE 自动生成,名字大致是这样,后面是版本号) 。 3. 在打开的该文件中右键点击,选择右键弹出菜单的“Build PKG File” 选项,创建 sisx 安装文件。至此,安装包制作完成,它的位置为 “<MyApp>\sis\<MyApp>_S60_3_X_v_1_0_0.sisx” 。 你会发现第三步生成 3 个文件,分别为: _resolved<MyApp>_S60_3_X_v_1_0_0.pkg <MyApp>_S60_3_X_v_1_0_0.sis <MyApp>_S60_3_X_v_1_0_0.sisx 文 件 1 是 <MyApp>_S60_3_X_v_1_0_0.pkg 的 实 例 化 文 件 , 您 会 发 现 <MyApp>_S60_3_X_v_1_0_0.pkg 中的不定因素都根据您的环境落实了,其实 IDE 是先生成它,然后由它生成安装文件。 文件 2 和文件 3 都是安装文件,不同的是文件 3 已经被 IDE 自动签名认证 了。您可以直接安装文件 3,或者拿文件 2 做特别的签名之后安装。

6.2. 安装过程中出现的错误提示
在手机上用安装包进行安装的时候经常会出现以下的提示: 证书错误,请与应用程序提供商联系。 这很可能是您使用了没有认证的安装文件。 证书尚未生效,已过期,或者手机的日期设置不正确。 这是因为证书的生效时间大于手机的当前时间,可以更改手机时间解 决。 证书过期。 这是因为证书的失效时间小于手机的当前时间,可以更改手机时间解 决。 不支持安装…… 这有可能是程序的版本不正确(如将第二版程序安装到第三版的手机

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

34/36

上) ,也有可能根本不是安装文件,只是后缀名恰巧符合。 无法安装。 一般是因为安装文件制作不正确。我首次安装就遇到这种情况。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

35/36

7. Symbian C++有效的学习方法
在本文中,我对 Symbian C++作了简略的介绍。这些内容仅是 Symbian C++的冰山一角,还不够格作为 Symbian C++的入门资料。我写本文的目的主 要是使您更直接地了解 Symbian C++,更顺利地进入她的世界。所以,要想真 正地学好 Symbian C++,还要靠您的自学。下面我总结一些学习 Symbian C++ 的方法。

7.1. 读程序
学习任何编程语言的捷径都是看前人所写的程序,特别是一个好的程序, 往往蕴含着语言的精华,等待着您的开采。 最开始的时候,您应该试着分析一个简单的程序,一般都是 HelloWorld 程 序,或 IDE 自动生成的程序框架。您可以设置很多很多断点,去详细分析程序 的流动过程。这是您了解程序运行基本框架的捷径。 之后呢,就可以选择一些较复杂的程序来分析。而更好的做法是选择那些 与您要实现功能接近的程序分析。这样做,您就能够大致了解一些特殊功能是 如何实现的,如何更好地实现的。这是您了解语言用法和快速开发的捷径。 随着您读的程序愈多愈复杂,您的功力就愈纯愈高深。 一般情况下,Nokia 的 SDK 开发包内都会附带一些例子程序。它们一般都 是针对框架、结构、机制、功能等的具体范例。 另外,Nokia论坛亦提供了大量的例子程序。如果您希望了解某些功能如何 实现,不妨在Nokia论坛的搜索页面将“Scope”设为“Examples” ,输入搜索关 键字进行搜索,往往能找到相关的例子程序。

7.2. 看文档
看文档是一个很重要的学习方法。通过读相关文档,您可以很系统地学到 诸如语法、规范、框架、机制、功能等多方面的知识,是您能力得以进阶的必 由之路。 读程序学到的知识是零碎的、片面的,只有通过看文档,才能够使您的知 识系统化、全面化。文档也是 Symbian C++的设计者与您交流的有效途径,看 文档使您更本质地了解一些关键问题。 您的 SDK 本身就带有文档,通过它,您可以对您的 SDK 有很好的了解。 另外 Nokia 论坛和 Symbian 网站都提供了大量的文档,这对于开发者来说 无疑是一个巨大的宝库。 Nokia 论坛提供了分类的文档目录,您也可以像查找例子程序那样,在 Nokia 论坛的搜索页面搜索您想要的文档。 在Symbian开发者网站中,您亦可找到关于Symbian OS和其SDK的大量文 件。

书蕴厚重以养志·剑走轻灵以通神

Symbian C++开发经验

36/36

7.3. 逛论坛
交流是一种很重要的学习方法。三人行必由我师,向能者请教,能够让我 们成长更快。在我们遇到难题时,论坛为我们提供了良好的交流平台。一个好 的论坛藏龙卧虎,他们每一个回复都可能使您受益匪浅。 下面提供一些和 Symbian C++开发相关的论坛。 CSDN是国内最大的综合性IT技术网站,它的CSDN论坛包含各种编程语言 的子论坛。其中就有关于Symbian的子论坛。 Nokia论坛是Nokia为其开发者提供技术支持的地方。它的Nokia社区集论 坛、WIKI、博客于一体,为Nokia开发者提供了很好的交流平台。 Symbian开发者网站有专门的论坛和WIKI,为开发者提供Symbian相关信息。 NewLC网站的论坛也是一个交流Symbian C++经验的好地方。

7.4. 我经常访问的网站
合理地利用丰富的网络资源使我们的学习工作更轻松。我将经常访问的网 站列举如下,希望对您有所帮助: CSDN网站:国内最大的IT技术网站。 Nokia论坛:为Nokia开发者提供技术支持。 Symbian开发者网站:为Symbian OS的开发者提供技术支持。 NewLC网站:Symbian C++开发者的交流平台。 开发视界:针对移动设备开发人员的技术网站。 Symbian OS系统开发中文翻译论坛:提供与Symbian 开发相关的中文 翻译文档。

书蕴厚重以养志·剑走轻灵以通神


相关文章:
塞班的特点.doc
塞班特点塞班系统分为功能机平台和智能机平台, 这是这个系统和其它几个主流的操...C 系:C5-00 C5-01。 X 系:X5-00,X5-01 .X10。 三星:G818E、i8510c、...
用C原生API写Symbian日志文件.doc
C原生API写Symbian日志文件 - 声明:是我参考网上一片文章加上自己的理解写出来的! 我们都知道 Symbian 里没办法象 PC 那样用 printf()、Symtem.out.pr...
基于CARBIDE.C 的SYMBIAN(NOKIA 手机)开发基础实验报告.pdf
基于CARBIDE.CSYMBIAN(NOKIA 手机)开发基础实验报告 -
Symbian类基础知识(一).pdf
SymbianOS 简介〗 1.1 SymbianOS的六大特性 1、操作系统是运行在ROM上的 2...3、通用清理项(General Cleanup Item)在默认情况下,清理栈只处理 那些 CBase-...
symbian 系统.doc
Symbian 是一个实时性、多任务的纯 32 位操作系统,具有功耗低、内存占用少等...(JSR139),MobileMedia (JSR135),3D 图像数据(JSR184), JTWI 1.0 c(JSR...
塞班系统c盘文件解析.txt
塞班系统c盘文件解析_IT/计算机_专业资料。塞班系统c盘文件解析全面解析S60智能机...下面介绍c:systemData这个文件夹 c:systemData这个文件夹记录程序初始化或运行时...
Symbian.doc
Symbian 操作系统是 Symbian 公司为手机而设计的操作系统,它包含联合的数据库、...Symbian C 39页 免费 Symbian操作系统 4页 1下载券 Symbian学习笔记 8页 1...
Symbian系统S60平台三版模拟器安装【SDK教程】.doc
由于 S60三版系统内核(EKA2)的更换(当 然还存在拥有实时内核 EKA2 的 Symbian OS v8.1b) ,对现有 C+ +编程的绝大多数*SIS 程序不支持,导致现阶段对其...
诺基亚手机格机方法及注意事项(塞班系统).txt
SymbianOS6.X Series60界面的智能手机,在插入MMC之后,系统一般存在4个逻辑存储驱动器:C(手机本身的用户存储,SX1有4M),D(虚拟盘,使用空闲运行内存虚拟的缓冲盘),...
网络时间与理论3~11章的答案.doc
A、Windows Phone B、Symbian C、Android D、ios 我的答案:ACD 4 APP 开发的盈利模式有( )。 ? ? ? ? A、广告模式 B、增值功能付费下载模式 C、单纯收费...
4、Symbian程序开发概述_图文.ppt
(MBM文件浏览器) 15 验证开发环境 1、使用bldmake命令:首先打开命令行窗口,进入 C:\Symbian\8.0a\S60_2nd_FP2_SC\Series60Ex\helloworldba sic\group子目录...
Symbian系统.txt
Symbian是一个实时性、多任务的纯32位操作系统,具有功耗低、内存占用少等特点,...(JSR139),MobileMedia (JSR135),3D图像数据(JSR184), JTWI 1.0 c(JSR185...
Symbian Sign.doc
Symbian Sign_IT/计算机_专业资料。关于申请Symbian Sign需要准备的材料和手续Symbian 应用程序签名指南 和 Symbian Signed 认证指南本签名指南根据 Symbian 文档《怎样...
塞班系统培训课件1_图文.ppt
C:版本之间兼容性差也是Symbian OS需要改进 : 的一个地方,每当新版本的Symbian OS发布并有 产品面世时,系统的兼容性便成了其发展的一个 大敌。相当多的一部分...
2012移动商务知识赛练习卷C.doc
和 MeeGo 能否改变移 动游戏 A.Windous Phone 7 B.Symbian C.Windows CE D.Linux (新)30. C )决定了商务活动的内容和范围,决定了我们能做什么和不能做...
SymbianS60介绍.doc
SymbianS60介绍_信息与通信_工程科技_专业资料。SymbianS60
Nokia塞班系统.txt
Nokia塞班系统。Nokia塞班系统介绍 ---...C(手机本身的用户存储,
如何搭建Symbian S60 5th的C++开发环境.doc
如何搭建Symbian S60 5th的C++开发环境_IT/计算机_专业资料。如何搭建 Symbian ...鼠标右键点击 C/C++ Projects 项目导航页中项目树中我们 刚建立的项目 MyFirst...
塞班Symbian系统手机成功安装未签名软件详细方法和软件包.doc
塞班Symbian系统手机成功安装未签名软件详细方法和软件包_信息与通信_工程科技_...C:\resource 文件夹中;再解压该压缩包里 Python 文件夹中的两个文件 Unsigned...
Symbian操作系统S60平台三版模拟器安装、使用(一).ppt
由于S三版系统内核(EKA) 的更换(当然还存在拥有实时内核EKA 的Symbian O S vb),对现有C+ Symbian操作系统S平台三版模拟器顺应S平台三版手机的 上市而发布,并...
更多相关标签: