SymbianOS应用程序结构.doc_第1页
SymbianOS应用程序结构.doc_第2页
SymbianOS应用程序结构.doc_第3页
SymbianOS应用程序结构.doc_第4页
SymbianOS应用程序结构.doc_第5页
已阅读5页,还剩32页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Symbian OS应用程序结构目 录1. Symbian OS SDK的介绍22. Symbian OS SDK的安装33.使用向导建立Symbian工程53.1建立Symbian EXE工程53.2建立Symbian DLL工程73.3 导入已有Symbian工程94.编译和运行Symbian程序104.1编译和运行EXE程序104.2编译和运行DLL程序125. Symbian OS应用程序结构145.1 EXE 程序的文件结构145.2 UID的申请方法165.3 EXE程序的结构175.3.1 Symbian程序的命名规则175.3.2 Symbian的异常处理机制205.3.3函数声明宏的含义245.3.4 堆检测宏255.3.5 EXE程序执行过程265.4 DLL程序的文件结构295.4.1概述295.4.2 RSS文件结构305.5 DLL程序的结构355.5.1 DLL程序执行过程351. Symbian OS SDK的介绍为了支持开发者为Symbian OS开发应用程序,合作厂商开发了适应各自手机的SDK。Symbian OS应用程序开发者首先要获得一个SDK,这些SDKs是免费提供的,可以在Symbian的官方网站或者合作厂商的网站上下载。Symbian OS SDKs支持Java和C+语言的开发。开发人员可以根据自己的需要来选择相应的SDK。这些SDKs提供以下功能:1、一组开发工具和多种API接口。2、所有API和开发工具的系统文档。3、Symbian OS手机模拟器,可以在PC机上运行。4、一些例子应用程序。由于Symbian OS本身不包括用户界面,所以,通常会由一些伙伴厂商为Symbian OS提供特定的用户界面平台(UI Platform),其关系就相当于Linux系统和X Window的关系。因此,SDKs都是基于一个特定的UI Platform来构建的。一个UI Platform提供一个独特的UI,还有一系列面向各种任务的相关系统应用程序。这些常见的任务包括:收发消息、浏览、电话功能、多媒体功能和联系方式/日历管理等等。这些应用通常都会使用由Symbian OS提供的一些应用引擎。那些打算支持一些用本地C+编写的第三方应用的安装的UI Platform必须要被相应的SDK支持才行。到目前为止,Symbian已经发行了多个版本,现在最流行的是Symbian OS v6.0版。从Symbian OS v6.0开始,共有以下各种版本的SDKs:UIQNokia Series 90Nokia Series 80Nokia Series 60Nokia 9200 Communicator series点击以上链接可以到Symbian的官方网站上获取更多关于该SDK的信息。其中,UIQ主要支持Sony Ericsson公司的智能手机,其它SDKs则支持Nokia公司的智能手机。对于应用程序开发者来说,在为特定的手机开发应用程序时,首先需要了解的就是与它相关的UI Platform以及该手机所使用的Symbian OS的版本。有了这两方面的信息,你就可以决定自己需要那个SDK了。在大多数情况下,依靠这个SDK,你就可以开发一个单一版本的应用程序,然后能够在所有的基于相同的UI Platform和Symbian OS版本的手机上运行。当然,即使两款手机支持的UI Platform相同,它们之间也会有少许差别。Symbian OS 系统定义文档给出了更进一步的细节信息,点击以下链接可以获取相关文档:Symbian OS System DefinitionSymbian OS System Definition - Detailed View (updated to include v8.0)2. Symbian OS SDK的安装安装Symbian OS SDK需要按照严格的顺序进行,否则SDKs将无法正确使用。目前,使用得最广泛的C+集成开发环境是Microsoft的Visual Studio平台,最流行的Symbian OS SDK是Nokia Series 60。现在以Visual Studio .net 2003平台上安装Nokia Series 60 v8.0为例,介绍Symbian OS SDK的安装过程。首先,PC机使用的操作系统推荐使用Windows 2000,因为SDK在Windows 2000下经过了完整严格的测试。当然,在Windows XP下,SDK一般情况下也可以正常运行,笔者在Windows XP下使用Nokia Series 60 v8.0目前没有出现任何问题,但是使用UIQ时却出现不明错误。操作系统选定以后,就要安装Visual Studio .net 2003了。该IDE最好和操作系统安装在同一个磁盘分区下,这样可以避免在开发应用程序时,经常在两个分区下转换。因为SDK的应用程序代码必须保存在操作系统的分区下。下一步,需要安装j2re。安装j2re是因为SDK自带的Aif Builder等工具需要它的支持,如果不安装,将无法使用这些工具。j2re可以到Sun公司的官方网站下载,推荐下载最新版本,也可以使用较早版本,但是一定要下载1.3.1版以后的版本。j2re也要安装在操作系统的分区之下。第三步,安装Active Perl,也要安装在操作系统分区之下。SDK需要Perl语言的支持。Active Perl安装包可以到Active Perl 的官方网站去下载,该链接附后,并注意下载Windows下的最新版本。/Products/Download/Download.plex?id=ActivePerl第四步,安装SDK,同样,安装在系统盘下,不要更改默认安装目录。到Nokia公司的官方论坛下载SDK for 2nd Edition, FP 2,如果需要中文支持,则下载SDK for 2nd Edition, FP 2 Chinese。该论坛需要用户首先进行注册,然后方可下载,链接附后。/main/0,6566,034-4,00.html第五步,安装Carbide.vs在系统盘之下,并且进行注册。Carbide.vs是专为Visual Studio .net开发的支持程序,它能够使Visual Studio自动生成Symbian工程,需要到Nokia网站上进行免费注册,获得注册码,如果不注册,只能使用十几天。下载链接如下:/main/0,6566,034-902,00.html下面,检验SDK是否安装成功。打开Visual Stuido .net,在File菜单下观察是否有import Symbian project选项,如图1所示,如果有,则表明安装成功。图13.使用向导建立Symbian工程3.1建立Symbian EXE工程现在我们尝试建立一个Symbian工程,SDK具有工程模板,可以很方便的生成Symbian工程。利用SDK可以开发两种类型的Symbian应用程序EXE和DLL,它们统称为可执行程序。其中EXE类似于一般的C+控制台程序,DLL即动态链接库程序。EXE是文本界面的,大多数应用程序并不是这种结构。DLL程序是具有图形界面的程序,手机应用程序多数是这种结构的。EXE程序的结构较为简单,我们首先建立一个EXE工程。打开Visual Studio,在File菜单中点击NewProject,出现如下画面(图2):图2在Visual C+ Projects目录中有Symbian OS选项,选中它,然后在Name中输入新建工程的名字,在这里为Symbian1,在Location中输入工程目录。需要注意的是,工程目录必须和Symbian SDK的安装目录位于同一磁盘分区下,否则在编译工程时可能出现问题。Name和Location定好以后,点击OK。出现下列对话框(图3):图3Project type不用改,默认为Classic类型。在Project template下拉菜单中选择Symbian EXE,然后点击Finish。至此,EXE工程建立完毕。查看屏幕左方的Solution Explorer,如图4所示,可以看到,一个最简单的Symbian EXE工程由位于5个文件夹中的8个文件所构成,在后面的文章中我们将会了解到这些文件的功能。图43.2建立Symbian DLL工程下面,我们再建立另一种可执行程序DLL的工程。大致步骤和建立EXE工程相同,只不过在图3的下拉菜单中,需要改成选择Symbian OS DLL,如图5所示。然后点击finish,DLL工程建立完毕。下拉菜单中其他类型的工程,除EXE工程外,都是DLL工程,只不过功能更加强化,我们现在建立的是最简单的DLL工程。浏览Solution Explorer可以发现,DLL工程的结构和EXE工程的结构有少许不同,主要差别在包含的文件有一些不一样,如图6所示。图5图63.3 导入已有Symbian工程Symbian SDK自带有许多例子工程,帮助程序员熟悉Symbian应用程序的编写过程。现在我们尝试打开最简单的例程helloworldbasic,为它建立工作区。打开Visual Studio .net,在File菜单中选择“Import Symbian Project”。如图7所示:图7接着出现图8所示对话框:图8在Project file中找到helloworldbasic.mmp文件,该文件位于Symbian的安装路径之下,和操作系统在同一个磁盘上,比如,在笔者的计算机中该文件位于:C:Symbian8.0aS60_2nd_FP2Series60Exhelloworldbasicgrouphelloworldbasic.mmp。然后,点击Next,在下一个窗口点击Finish,即可完成工作区创建过程。4.编译和运行Symbian程序4.1编译和运行EXE程序现在,我们按照上述步骤重新生成一个EXE,命名为HelloWorld。工程建立好以后,编译该程序。在Visual Studio的菜单栏中点击BuildBuild Solution,或者直接按快捷键F7,即可编译工程。然后,在Debug菜单中点击Start,或者F5,开启调试程序。调试程序调出SDK自带的模拟器来运行这个程序。模拟器类似于BREW中的模拟器,它模仿真实手机的功能,开发应用程序使用模拟器已经足够,不必将程序下载到真机上调试。该程序在模拟器中打印“Hello world!Command line args:“”press any key”字符串。运行界面如下所示(图9):图9EXE程序还可以通过命令行运行,就像运行DOS程序一样。调出Windows自带的命令行输入程序cmd.exe。使用DOS命令cd转换到生成的.exe程序所在的文件夹中,这个文件一般位于系统盘中,比如笔者的系统盘是C: ,则其位于C:Symbian8.0aS60_2nd_FP2epoc32releasewinsudeb中。键入命令行Helloworld.exe则模拟器被调出,程序运行与上面一样。还可以添加命令行参数,如果键入Helloworld.exe LiuNing,则args后的引号中会出现字符串LiuNing。如图10所示。图104.2编译和运行DLL程序首先,按照第三节的方法建立一个DLL工程,这一次在下拉菜单中选择S60 Simple HelloWorld Application,这个模板生成的DLL程序可以显示“Hello World”字符串。将该工程也命名为HelloWorld。然后在Visual Studio中编译和调试,方法和EXE工程一样。DLL程序需要图形界面,需要的开销较大,因此编译速度以及模拟器的启动速度要比EXE程序慢的多。模拟器启动以后,可以看到屏幕上有很多图标,使用PC键盘方向键,或者用鼠标直接在模拟器的方向键上点击,找到名为HelloWorld的图标。如图11所示。点击模拟器上OK键进入HelloWorld程序。该程序运行后如图12所示。点击模拟器左边的软键,出现一个菜单,选择Test项,程序显示出一个字符串“Hello World”,字符串右边还有感叹号动画,如图13所示。持续大概3秒钟,程序又跳回初始画面。按右边的软键,退出程序。DLL程序不能使用命令行方式运行。图11图12图135. Symbian OS应用程序结构5.1 EXE 程序的文件结构打开刚才建立的HelloWorld EXE工程。EXE工程都由5个文件夹构成:group,inc,sis,src,tsrc。下面对这些文件夹中的各种文件进行介绍:group文件夹:1 bld.inf组定义文件该文件指明了工程平台和工程的项目定义文件名,主要在构建(Build)工程时起作用,在编程过程中一般不必改动。内容如下:PRJ_PLATFORMSWINS WINSCW THUMBPRJ_MMPFILESHelloWorld.mmp其中,HelloWorld.mmp就是该程序的项目定义文件名。这种文件在简单的工程中通常只有一个,在负责的程序中,可能需要多个项目定义文件。2 HelloWorld.mmp项目定义文件该文件规定了EXE目标程序名,目标程序类型等信息。文件内容如下:TARGET HelloWorld.exeTARGETTYPE exeUID 0USERINCLUDE .incSYSTEMINCLUDE epoc32includeSOURCEPATH ./DOCUMENT readme.txtDOCUMENT bld.infSOURCEPATH .srcSOURCE HelloWorld.cppLIBRARY euser.lib从文件内容可以看出,UID也在此文件中列出了。和BREW程序一样,Symbian应用程序也需要向Symbian公司申请唯一的UID号,不过申请是免费的。Symbian的UID由两个8位十六进制数描述,其中第一个数由PC机自动生成,第二个数需要向Symbian公司申请。申请方法将在下一节中介绍。mmp文件中还规定了用户和系统的文件包含目录,源代码目录,程序文档和组定义文件名,用户库等信息。在编程过程中,这些信息回发生改变,一般由程序自动完成,程序员无需操心。3helloworld.uid.cppUID记录文件该文件中记录了该工程的UID信息,内容如下:#include #pragma data_seg(.E32_UID)_WINS_UID(0x10000079,0,)#pragma data_seg()可以看到,Symbian的UID由两个十六进制数组成,其中第二个数0就是mmp文件中UID项中的值。4readme.txt该文件是一个普通的文档,介绍了工程的编译方法,与程序主体无关,与MFC工程中的readme.txt文件类似。inc文件夹:1HelloWorld.h该文件中主要包含了对E32Main()函数的原型声明。E32Main()函数是EXE程序的入口函数,类似于C语言中的main()函数。sis文件夹:1HelloWorld.pkg该文件规定了从helloworld.exe生成sis文件。sis文件是下载到真实手机中运行的文件,和BREW中的mod文件类似。这个文件在编程过程中用不到。src文件夹:1HelloWorld.cpp源代码文件毫无疑问,这个文件是最重要的。程序员的主要任务就是编写源代码。随着程序规模的增大,类的增多,.cpp和.h文件也会越来越多。当然,源代码的风格和普通的C+代码有些不一样。在后面的章节里,将会介绍Symbian源代码的大致结构。tsrc文件夹:1readme.txt这个文件也是一个普通的文档,程序员可以在里面描述程序的功能等等一些信息。该文件与程序主体无关。5.2 UID的申请方法现在介绍申请UID的方法。往中发送一封标题为“UID request”的邮件,并且在邮件中写明请求多少个UID,一般一次申请10个左右,以及你的名字和回信地址。在24小时内,你的信箱将收到相应数目的UID。5.3 EXE程序的结构打开HelloWorld.cpp文件。这个文件里面有3个函数,首先找到E32Main()函数,这个函数是所有EXE程序的入口函数。Symbian的EXE程序和C+ Console程序的结构非常类似。都是从Main()函数进入,依次执行函数内部的各条语句,直到Main()函数内部所有语句执行完毕,最后返回。在分析EXE程序结构之前,我们需要了解一下Symbian不同于普通C+语言的一些处理机制。5.3.1 Symbian程序的命名规则Symbian OS上的应用程序使用一组标准的约定来命名类(class),结构(struct),变量(variable),函数(function),宏(macros),枚举类型(enumeration)和常量(constant)。本小节粗略地解释这些命名的含义:一类(class)的命名:大多数类的命名是通过加前缀字符C,T,R,M构成的。下面简单说一下它们表示的意思:C:C前缀表示该类从CBase类派生而来,这样的类较为复杂,占用的内存空间较大,应该在堆上进行构造。例如:CAknDocumentT:T前缀表示一个简单类,这种类不拥有任何额外的资源,没有析构函数。大量的基本数据类型属于这种类型。例如:TIntTBoolR:R前缀表示一个资源类,它包含其它位置拥有资源的句柄。例如:RFileRTimerM:M前缀表示一个接口类,由纯虚函数构成,不包含成员数据。它定义了接口但需要派生类实现。它是Symbian OS中唯一允许使用多重继承的类。例如:MGraphicsDeviceMapMGameViewCmdHandler另外,那些由静态函数构成的类,没有前缀字符。例如:UserMath除了前缀字符以外,类名通常用一个名词表示该类的用途。以上的例子都满足这个要求。二结构(struct)的命名:结构(struct)类型一般作为T类对待,因为它也不拥有任何额外的资源,没有任何成员函数,它的前缀通常是T,但也有一些以S开头。例如:SEikControlInfo三变量的命名:成员变量的名字以i开头,代表instance,例如:iMember这样可以很容易检查某些清除相关的规则。参数名以a开头,代表argument,例如:aControlaIndex局部变量命名不需要前缀字符。例如:device全局变量应尽量避免使用,如果实在需要,使用时第一个字母大写。例如:OppFleetViewSymbian不使用匈牙利命名法或者其它在名字中包含类型信息的命名方法,Symbian的设计者认为那样看起来很复杂,并且当系统有几百个类时不容易管理。四函数的命名:函数的名字应当指出它要做什么,通常用动词表示。但是获得某个量的值的函数例外,比如,一个返回成员变量的函数,它的名字通常是除去前缀“i”的变量名: inline RWindow& Window() const return iWindow; ; 与之相反,设置设置某个量的值的函数包含单词“Set”,例如:SetWindow()出现错误而终止函数时Symbian平台并不使用标准C+的异常处理,它有自己名叫leave的异常处理系统,有自己的命名方式。关于这一点将在异常处理机制一节中阐述。获得对象的所有权并销毁它的函数的名字以D结尾,代表destroy。UI框架中对话框的例子:CEikDialog* dialog=new (ELeave) CBossSettingsDialog;if (dialog-ExecuteLD(R_BOSS_SETTINGS_DIALOG) / handle successful settings ExecuteLD()函数包含第二阶段构造,它执行显示对话框然后销毁它的操作。五宏的命名:宏的名字全部用大写表示并用下划线分隔单词。例如:#define _UHEAP_MARK User:_DbgMarkStart(RHeap:EUser)六枚举类型的命名:枚举类型按下面的方法命名: 1如果把枚举类型当做简单类型,拥有T前缀;2枚举类型成员拥有E前缀;3类型和成员名应该是有意义的,没有二义性的名字。枚举类型应当被封装到相关的类里,这样才不会与全局名字产生冲突。下面是一个定义和使用枚举类型的例子:class TDemo public: enum TShape EShapeRound, EShapeSquare; ; TDemo:TShape shape=TDemo:EShapeSquare; 七常量的命名:常量名包含一个K前缀,例如:const TInt KMaxNameLength=0x20; 5.3.2 Symbian的异常处理机制刚刚接触Symbian代码时,感觉最不适应的可能就是经常看到PushL()和Pop()函数,以及很多的函数都有L或LC的后缀。其实这是Symbian的异常处理机制。比如,我们定义了一个指针,给它分配了空间,可是在使用它的时候程序突然出现了致命错误,被迫中止,这样被这个指针占用的地址空间我们就收不回来了。在PC机上,出现这种情况一般不会造成严重后果,因为物理内存较多,而且PC机一般运行不长的一段时间后就需要重启动了,丢失的内存空间就会回收。Symbian的设计者可能认为这些在手机上是行不通的,因为:1各种 Symbian OS 应用程序都需要能长时间运行(几个月,甚至几年)而不发生中断或系统重启。2各种 Symbian OS 应用程序都需要在具有稀缺资源,特别是内存有限的设备上运行。因而,比起PC机上的应用程序,Symbian上的应用程序更容易出现资源用尽的情况。 3不同制造商生产的Symbian OS 设备拥有的资源不相同,也就是说,为某类 Symbian OS 设备设计并通过验证的应用程序可能在其他制造商的设备上发生资源性异常。因此,设计者们对这一点做了很多的设计。Symbian有一个CleanupStack清除堆栈,在使用指针时,用PushL()把指针压入堆栈中,使用完后再用Pop()弹出堆栈。因为手机中的硬件软件资源是非常稀缺的,因此,在某些函数调用过程中,可能导致系统崩溃,例如,机器用尽了内存,或者某个通讯端口当前不可用等等,这种因资源缺乏而导致的出错,称为异常(Exception)。如果果真出现了问题,那么CleanupStack可以通过调用该指针的析构函数回收占用的空间。这些可能导致系统崩溃的函数在Symbian里被称为 “可能Leave”的函数,所以就在这些函数的尾部加了一个L。而加LC后缀的函数表明该函数已经在内部把指针用PushL()压入CleanupStack了,调用时无需再用PushL(),直接调用完用Pop()即可。CleanupStack还提供了一个PopAndDestroy()函数,就是弹出栈后再销毁指针。正是因为有了CleanupStack机制,所以Symbian程序在有些地方看起来跟VC的程序不太一样,比如说很多类的构造函数都不用,而是用NewL()或NewLC()构造,分配地址时的操作符New()也变成了New(ELeave)。在传统的C+程序中,往往用一个if语句来检查是否发生了资源用尽出错。比如:myObject = new CSomeObject();if (myObject = = NULL) PerformSomeErrorCode();使用这种传统解决方法会产生两方面的问题:1需要在每个可能导致资源用尽错误的独立函数周围放置许多额外的代码。这样就会增加代码量,并降低可读性。2如果某个构造函数无法分配资源,就无法返回一个出错代码,因为构造函数没有返回值。结果就可能是一个不完整的被分配对象,这可导致程序崩溃。C+异常处理(try,catch及throw)机制为这些问题提供了一些解决方案,但并没有被Symbian OS 采用,因为代码开销较大。因此,Symbian OS 提供其特有的异常处理系统。规则如下:规则 1:所有可能异常退出的函数名都以字母L结尾。各种异常都顺着调用栈通过一些“异常函数”向后传递,直到被一个Trap Harness捕获模块,捕获为止。通常在针对各种控制台应用程序的 E32Main() 主函数中实现这一功能,或作为图形用户界面程序的应用框架的一部分提供。规则 2:当在堆中分配内存时,如果指向该内存的指针是一个自动变量(即不是成员变量),必须将其推入清除堆栈中,以便当发生异常退出时能被释放掉。所有被推入该清除堆栈的对象都必须在销毁前弹出。规则 3:C+构造函数和析构函数是不允许异常退出或失败的。因而,如果某个对象的构造函数可能出现资源不足异常而失败,则这个构造函数中所有可能导致失败的指令都必须移出,并将它们放入到 ConstructL()函数中,在 C+构造函数完成之后再调用该函数。这一过程被称为Two Phases Construction两阶段构造。Symbian OS中的函数并不返回出错代码,而是在出现资源不足错误时,立即异常退出。一个异常退出就是对函数User:Leave()的调用,它导致程序的执行被立即返回到捕获模块中,该函数就在其中执行。所有可以异常退出的函数都以字母“L”结尾。例如以下用户自定义的函数:void MyFunctionL() iMember = new (ELeave) CMember; iValue = AnotherFunctionL(); User:LeaveIfError(iSession.Connect(); MyFunctionL()中的每一行都可能导致异常退出。其中的任何一行都使MyFunctionL()成为一个异常退出函数。然而需要注意的是:应用程序代码中很少有必要使用 TRAP,因为应用框架已经在适当的地方提供了这些捕捉错误的代码,也提供了相应的处理代码。在正常编码过程中并不需要使用错误捕捉代码。一般说来,处理各种异常退出的方法很简单,就是在函数名字后面加上一个字母“L”,从而让其能顺着函数传递。在Symbian OS 中,分配内存的运算符new的失败可能性很高,以至于该运算符已经被重写,而且还带上了一个参数,即Eleave。当用这个参数调用new时,如果内存分配失败,被重置的new运算符就会异常退出。这一功能已经得到了全局性实现,所以,任何类都可以使用该运算符的new (ELeave) 版本,如:CSomeObject* myObject = new CSomeObject; if (!myObject) User:Leave(KErrNoMemory); 可以被替换为:CSomeObject* myObject = new (ELeave) CSomeObject;Symbian OS 的类经常需要实现NewL()和 NewLC()方法,这两个方法是对new (ELeave) 操作的封装。它们在类定义中被声明为static方法,这就使得它们可以在该类的一个实例存在之前就被调用。可以使用:域解析运算符来调用它们。如:CSomeObject* myObject = CSomeObject:NewL();NewL()在堆上创建了该类的一个新实例,当出现内存不足错误时,它就会异常退出。对简单对象来说,这仅仅涉及到对 new (ELeave) 的调用。但是,对对复杂对象来说,它要用到两阶段构造,需要调用NewLC()函数。例如,helloworldbasic例子中CHelloWorldBasicDocument的NewL():CHelloWorldBasicDocument*CHelloWorldBasicDocument:NewL( CEikApplication& aApp ) CHelloWorldBasicDocument* self = NewLC( aApp ); CleanupStack:Pop( self ); return self;正如前文所述,NewLC()在堆上创建了该类的一个新实例,获得一个指针,并使用PushL()将指针推入到清除堆栈,如果出现了内存不足错误,就发生异常退出。当创建C类对象时,如果某个成员函数会指向该对象,就应该在程序中使用 NewL();而如果某个自动变量会指向该对象,就应该使用 NewLC() 。但是,并不建议对每个类都实现NewL()和NewLC()。实际上,如果仅仅在应用程序中的一个地方调用NewL()和 NewLC(),实现它们的代码比起所保存的要多许多。较好的做法是:对每一个类都作评估,看看其是否需要用到NewL() 和NewLC()。 TRAP 和TRAPD捕获模块:TRAP和 TRAPD是Symbian OS 提供的两种功能非常相似的捕获模块宏。在出现异常的情形中,开发者可以用一个捕获模块来处理一个异常。然而,TRAP和 TRAPD的使用仅限于特殊情况,而对所有的一般性编码来说,则应避免使用。通常,最佳反应过程是:允许该异常退出传递回Active Scheduler(活动调度器),以便进行默认处理。如果不能确认是否真正需要使用捕获模块,应该用经济的且明了的方法,实现相同的功能。当捕获模块中的代码执行发生异常退出时,程序控制立即返回给这个陷阱宏。然后该宏返回一个可以由调用函数使用的出错代码。要在某个捕获模块中执行一个函数,可以使用TRAPD,如下所示:TRAPD(error, doExampleL();if (error != KErrNone) / Do some error codeTRAP与TRAPD的不同之处仅仅在于:前者的程序代码必须声明异常代码变量。TRAPD用起来更方便,因为在宏的内部声明了异常代码变量error。如果用TRAP,上述代码就变成:TInt error; /声明异常代码变量TRAP(error,doExampleL(); if (error != KErrNone) / Do some error code所有被 doExampleL()调用的函数也在捕获模块内部执行。在doExampleL()内部嵌套的任何函数如果发生了异常退出,也将返回到这个捕获模块中。其他的TRAP模块也可以被嵌套在第一个内部,这样就可以在该应用程序内部的不同级别上对所有的出错进行检查。5.3.3函数声明宏的含义函数声明宏即:GLDEF_C,LOCAL_C,GLREF_C,IMPORT_C和EXPORT_C等。在Symbian OS应用程序中,很多函数都有这些声明,所有这些宏都被定义在 e32def.h头文件中。如GLDEF_C,LOCAL_C和GLREF_C的定义:#define GLREF_D extern#define GLDEF_D#define LOCAL_D static#define GLREF_C extern#define GLDEF_C#define LOCAL_C static后缀_D和_C是Symbian的一个约定,_D指数据声明(declaration of Data),_C 指代码定义(definition of Code)。这里,static被LOCAL_C和LOCAL_D所取代。GLREF_C和GLREF_D被指定为全局引用(GLobal REFerence):extern 。GLDEF_C和GLDEF_D指定了一个全局定义(GLobal DEFination)。这两个宏没有给出一个固定的定义,但是它们被作为函数和变量的记号。IMPORT_C的定义如下,意思是从 DLL 中导入函数。#define IMPORT_C _declspec(dllexport)如果一个DLL函数要被导入到应用程序,那么这个函数必须首先以 IMPORT_C声明,告诉编译器,这个函数可以在DLL中找到。EXPORT_C的定义如下,意思是从DLL中导出函数。#define EXPORT_C _declspec(dllexport)如果一个函数是DLL API的一部分,并且要在应用程序或其他DLL中被调用,那么这个函数在C+源文件中必须实现为导出。5.3.4 堆检测宏EXE代码中常常会有_UHEAP_MARK,_UHEAP_MARKEND等宏。这些宏是用于检测内存的分配情况的。只需要把这些宏加入你要检测的代码部分即可,它们的作用如下表所示:宏功能_UHEAP_MARK开始检测堆的使用状况_UHEAP_CHECK(n)检测自上一个_UHEAP_MARK是否有n个堆被分配(尚未释放)_UHEAP_CHECKALL(n)检测是否有n个堆已分配_UHEAP_MARKEND检测结束,并检测在_UHEAP_MARK之后有没有未被释放的堆_UHEAP_MARKENDC(n)检测结束,并检测在_UHEAP_MARK之后有无n个未被释放的堆现举一例:CMyClass * a1 = new(ELeave) CMyClass;._UHEAP_MARK; /开始检测CMyClass * a2 = new(ELeave) CMyClass;CMyClass * a3 = new(ELeave) CMyClass;._UHEAP_CHECK(2); /检测在_UHEAP_MARK之后有2个堆单元被分测(a2,a3)_UHEAP_CHECKALL(3); /检测三个堆已被分配(a1,a2,a3)delete(a2);_UHEAP_MARKEND; / 结束检测,a3内存泄露5.3.5 EXE程序执行过程HelloWorld中,函数调用关系为:1 E32Main函数调用DoStartL函数。2 DoStartL函数再调用MainL函数。各函数作用描述如下:GLDEF_C TInt E32Main() / Create cleanup stack /*开始内存检测*/ _UHEAP_MARK; /*分配和创建清除栈,如果创建成功,该清除栈就成为当前的清除栈。*/CTrapCleanup* cleanup = CTrapCleanup:New();/ Create output console/*分配和创建输出控制台,并且使用TRAPD宏捕获异常,返回错误值。*/TRAPD(createError, console = Console:NewL(KTextConsoleTitle, TSize(KConsFullScreen,KConsFullScreen);/*如果出现异常,则返回错误值,并退出。*/if (createError)return createError;/ Run application code inside TRAP harness, wait keypress when terminated/*调用DoStartL函数,并且使用TRAPD宏捕获异常,返回错误值。*/TRAPD(mainError, DoStartL();/*如果出现异常,则打印错误信息。*/if (mainError)console-Printf(KTextFailed, mainError);/*在console上输出字符串 press any keyn*/console-Printf(KTextPressAnyKey);/*等待用户输入任意键,相当于C+中getchar函数。*/console-Getch();/*释放console和cleanup的空间。*/delete console;delete cleanup;/*检测堆结束*/_UHEAP_MARKEND;/*返回无错误值,退出。*/return KErrNone;/*/LOCAL_C void DoStartL()/ Create active scheduler (to run active objects)/*分配和创建活动调度器,但是还未安装。*/CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();/*把scheduler指针压入清除栈中,如果发生leave则自动释放内存空间。*/CleanupStack:PushL(scheduler);/*安装活动调度器,安装成功后,这个调度器就成为当前的调度器。*/CActiveScheduler:Install(scheduler);/ Call main function with command line/*创建接受命令行的缓冲区。*/TBuf cmdLine;/*创建一个内核对象,调用CommandLine函数,接受命令行输入。该程序可以用命令行方式运行。*/RProcess().CommandLine(cmdLine);/*调用MainL函数。*/MainL(cmdLine);/ Delete active scheduler/*从清除栈中弹出scheduler指针,并且释放该指针的空间。*/CleanupStack:PopAndDestroy(scheduler);/*/LOCAL_C void MainL(const TDesC& aArgs)/*在console上输出字符串,相当于函数puts。*/console-Write(_L(Hello, world!n);/*输出格式化的字符串。相当于函数printf。*/console-Printf(_L(Command line args: %Sn), &aArgs);编写EXE程序的主要任务就是添加类和各种静态函数。编程过程和C+控制台程序类似。EXE程序的结构较为简单,在实际的应用中一般不会使用,因为它毕竟不是图形界面的,哪个智能手机的用户会去使用文本界面的程序呢?因此,EXE一般只是用来熟悉API,或者测试程序。5.4 DLL程序的文件结构5.4.1概述DLL程序是图形界面的,几乎所有的Symbian应用程序都是DLL程序。DLL程序的主要文件和EXE程序相似。打开Symbian SDK自带的helloworldbasic例子程序,可以看到该工程由6个不同的文件夹构成。src文件夹:包含该工程的C+源文件,与EXE工程一样。data文件夹:1Helloworldbasic.rss资源文件该文件定义了程序中所使用的各种资源,比如字符串,快捷键,菜单栏等。文件结构在后面将详细分析。2Helloworldbasic_caption.rss该文件同样是一个资源文件,定义了该

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论