490 likes | 693 Views
手机应用开发 symbian 的 C++ 编码规范 字符串和描述符 活动对象 错误处理与清理 客户端-服务器框架. 王旭. Symbian 的 c++ 编码规范. 基本类型 基本类型使用 命名约定 类命名规则 数据命名规则 函数命名规则 API 类 接口 不良做法. 基本类型. TInt8 TUint8 TInt16 TUint16 TInt32 TUint32 TInt Tuint TReal32 TReal64 TReal TText8 TText16 TBool TAny. 基本类型使用.
E N D
手机应用开发symbian的C++编码规范 字符串和描述符 活动对象 错误处理与清理 客户端-服务器框架手机应用开发symbian的C++编码规范 字符串和描述符 活动对象 错误处理与清理 客户端-服务器框架 王旭
Symbian的c++编码规范 • 基本类型 • 基本类型使用 • 命名约定 • 类命名规则 • 数据命名规则 • 函数命名规则 • API • 类 • 接口 • 不良做法
基本类型 • TInt8 TUint8 • TInt16 TUint16 • TInt32 TUint32 • TInt Tuint • TReal32 TReal64 TReal • TText8 TText16 • TBool • TAny
基本类型使用 • 使用整数的地方尽量使用Tint • 尽量不要使用浮点,除非必须的情况。科学计算可使用TReal • 函数返回的布尔值尽量使用TBool,不要使用TInt, • 表示布尔值应该使用ETrue和EFalse, • 不要布尔值进行值比较 • 要表示“无”的含义可以使用void 要表示“一切对象”要使用TAny *
命名约定 • 命名使用有意义的单词,不要使用太简略的缩写。 • 类名应该使用首字母表示类的基本属性,类名应该保证为名词形式 • 数据名也使用首字母表示其类型,数据名也应该是名词形式 • Symbian里的函数命名则更加重视末字母。 • 宏的命名一般使用大写字母并使用下划线分隔单词,和生成相关的宏应附加使用双前缀下划线和双后缀下划线。
类命名规则1 • T类没有析构函数,类似内置类型,所有的typedef都是T开头,T类可作为自动变量分配,作为其它类的成员分配。TFileName是个例外。 • C类是从CBase继承的所有类,C类总是在默认堆上分配,分配时所有的数据都被初始化为0,CBase包含虚析构函数,可通过CBase * 指针调用delete,正确析构它指向的任何C对象。 • R类,是拥有资源而不是位于默认堆上的所有类,通常可分配为成员变量或自动变量,大部分R类使用close() 来释放资源
类命名规则2 • M类是接口,是由纯虚函数组成的,不包含成员数据,实现该接口的类应当从它派生得来,Symbian里,M类是唯一允许使用多重继承的类。 • 静态类,是完全由不能实例化为对象的静态函数组成 • 结构是C风格的struct,无任何成员函数,不过Symbian很少使用这种类型,多数struct都使用T类
数据命名规则 • 枚举变量 本身用T,成员用E • 常量 使用K • 成员变量 使用i • 参数 使用a • 自动变量 使用有意义的名词
函数命名规则 • 非异常退出函数 使用合适的动词, • 异常退出函数 使用L • LC函数 • 简单getter 使用名词 • 复杂getter 使用Get • Setter 使用Set
函数 • C++头文件的函数原型可提供大量的信息,如是否虚拟,是否为static,是否可以异常退出,返回类型,行为提示,所有参数类型和方法等。 • 函数的参数可以分为按值,按&引用,按*引用三种,通常情况下使用按&引用,尽量不要使用按值的传递
API • 组件提供出来让其它组件调用的方法就是API • 组件X不但可以通过API被其它组件使用,也可以让X使用其它组件,如GUI框架可以调用函数让相关函数处理事件,也可以提供可被调用进行绘图的函数 • 因此,API可以分为库API和框架API
API-DLL导出 • DLL中交付的API需要在头文件声明 • 函数如果是作为API的一部分交付,则其在头文件声明的类必须是public,还必须从它的DLL导出 • 导出的这些类方法需要使用IMPORT_C • 在实现函数的c++文件里需要使用EXPORT_C
类 • 类用来表示对象,抽象,和接口的定义,类之间的关系用于表示对象间的关系 • 类与类之间的关系主要是四种 A use b A has b A is b A 实现 b
接口 • Symbian广泛的使用了接口类 • 接口需要使用特殊的类实现 • 接口是无数据,仅包含纯虚函数的抽象基类
不良的做法 • 私有继承 • 多重继承 • 改写有价值的虚函数
字符串和描述符 • 描述符 • 字符串和内存 • 修改字符串 • 标准描述符函数 • 其他API • Unicode和字符转换 • 二进制数据
描述符 • Symbian中,字符串是通过描述符实现的,描述符为处理字符串和通用的二进制数据提供了一种安全和连续性的机制,从而无需考虑所占用的内存空间类型 • 由于在symbian系统中,内存管理非常重要,所以使用描述符的时候必须充分意识内存管理的问题。
字符串和内存 • 字符串存在的三种类型 • 通用C中的字符串 • Symbian 的字符串
字符串存在的三种类型 • 存在于程序的代码区的字符串 • 存在于栈的自动对象 • 存在于堆上的动态对象
通用C中的字符串 • static char helloram[]=“hello”; const char* helloptr=helloram; • char hellostack(sizeof(Helloram)); strcpy(hellostack,helloram); • char * helloheap=(char*)malloc(sizeof(helloram)); strcpy(helloheap,helloram);
Symbian 中的字符串 • _LIT(KHelloRam,”hello”); TPtrc HelloPtr (KHelloRam); • TBufC<5> HelloStack(KHelloRam) • HbufC* HelloHeap=KHelloRam().AllocLC();
修改字符串 • 通用C中修改字符串的API不会进行内存分配,需要程序严格控制和判断缓冲区的大小,出现越界会导致在运行期发生不可预料的问题 • JAVA的字符串可以自动分配和释放内存,但是占用更多的内存空间 • Symbian里提供的描述符API也不进行内存分配,也需要自行控制缓冲区,但是越界的问题会在调试过程被展现出来。
如何修改HBufC • symbian不存在HBuf类,修改堆上的描述符还需要使用HBufC,首先需要使用NewLC()分配足够大小的内存,然后用TPtr指针来进行数据拷贝 • 语法如下: HBuf* helloworldHeap=HBuf::NewLC(KHelloRam().Length() + KWorldRam().Length()); TPtr helloworldAppend(helloworldHeap->Des()); helloworldAppend =KHelloRam; helloworldAppend.Append(KWorldRam);
标准描述符函数 • 基本函数,Length、MaxLength、size • 比较 • 搜索 • 提取 • 清除,设置 • 操作数据 • 字母操作 • 修剪和对齐 • 格式化
错误处理与清理 • 错误处理的类型 • 处理内存不足的错误 • 清理规则 • C类和T类 • R类 • 用户错误 • 严重提示 • 测试引擎和库
错误处理的类型 • Panic是指程序开发员处理不当导致程序出现的异常,如数组越界 • Exceptions是指程序运行在不正常状态导致异常,这不是程序员的错误。 • 当发生例外的时候,程序会抛出异常,离开正在执行的函数并返回集中的例外处理,这个就是leave。 • 处理抛出的例外的就是TRAP
处理内存不足的错误 • 设置堆平衡检查 • 正确销毁对象 • 不要分配或删除两次 • 不能成功分配内存就退出 • 使用错误捕获机制 • 使用清理框架机制
清理栈使用规则 • 使用清理栈解决如下问题:清理在堆上分配,但是指向它的唯一指针是自动变量的对象 • 只在需要解决这个问题才使用清理, • 不能把成员变量推入清理栈 • 任何从CBase派生的类都可以被推入清理栈
两阶段构造 • 由于清理栈用于保存指向基于堆的对象的指针,就意味着必须有机会把对象推入清理栈。 • 在new执行分配操作和随后调用构造函数之间做不到这点,这要求一种规则让C++构造函数不能退出,所以我们使用两阶段构造函数ConstructL(),让构造函数里不包含任何可能导致异常退出的代码,分配资源等的代码
C类和T类 • C类函数从CBase继承而来,在堆上分配,当不需要它的时候,一定要清理 • 如果C类只是在一个可能退出的函数中,由一个自动变量唯一引用,就应该把这个函数推入清理栈中。 • 对于任何C类,CBase的作用只有两个,完成零初始化,保证清理栈框架运行正确 • T类很少需要清理,如果在堆上显式分配T类对象,也需要使用清理栈
R类 • R类使用需要区分场合 • 可以用leaveIfError处理通常使用的R类对象 • 如果R类作为自动变量分配使用,就需要注意使用清理栈机制。
用户输入错误的处理 • 清理框架相当优秀,还可以被用于处理除了资源短缺以外的各种错误类型。如处理用户输入的错误
严重提示的知识 • 为了寻找程序错误导致运行不正确,可以使用Panic(), • 可以使用DEBUGGER()宏,它允许调试器从严重提示函数的完全上下文启动,方便寻找漏洞 • 可使用_ASSERT_DEBUG和_ASSERT_ALWAYS辅助完成错误代码定位。
活动对象 • 活动对象原理 • 工作方式 • 活动对象模式
活动对象的工作原理 • Symbian 系统设计专门为事件处理进行优化,所有事件都由活动对象处理。 • 事件处理线程有一个活动规划器,它决定处理事件的顺序
工作方式 • 一个线程可能有多个活动对象,每个活动对象都和一个具有请求函数的对象关联,这些请求函数将异步完成他们的请求,结束后将产生一个事情 • 活动规划器负责检测事件的发生,从而将该事件与请求它的活动对象进行关联,并且调用活动对象上的RunL() • 如果规划器无法找到与某个事件关联的活动对象,就会导致线程出现严重错误提示。
活动对象模式 • 活动对象可用于完成维护未完成的请求 • 可用于实现状态机 • 可用于处理完成的接口 • 可用于长期运行的任务和增量接口
客户端-服务器框架 • 处理常规请求 • 性能
处理常规请求 • 服务器与客户端运行在不同线程上(通常是不同的进程),symbian 核心通过消息传递和线程间数据传输来跨越线程边界 • 常规消息通过客户端-服务器会话传递。 会话包括RSessionBase、CSession、RMessage三部分, 客户端从RSessionBase派生,可以使用Send() 服务端从CSharableSession派生,通过ServiceL()检查请求,调用处理函数,并使用Complete()提交返回。
客户端与服务器的会话过程 • 建立会话 • 启动服务器 • 处理异步请求 • 结束会话并在客户端消亡后清理 • 在服务器消亡后清理
性能 • 事务的频率和事务的主要操作所需要的开销会影响系统性能 • 消息发给不同进程中的服务器开销最大 • 服务器与客户端处于相同进程中时,效率最高 • 多个进程间的线程间数据传输也需要相当多资源 • 相同进程中,线程间数据传输需要较少的开销
提高性能的方法 • 使用客户端缓冲 • 使用复杂的事务,一次完成更多工作 • 使用数据缓存 • 使客户端和服务器在相同进程中运作 • 使用共享内存
其他信息 联系方法:邮箱: wangxu@moabc.com MSN: xuwag@hotmail.com 以前的课件下载地址如下: • http://www.javayou.com/html/diary/showlog.vm?sid=2&cat_id=-1&log_id=3293 • http://www.dlog.cn/uploads/intro.ppt • http://www.dlog.cn/uploads/sp.ppthttp://www.dlog.cn/uploads/j2me.ppthttp://www.dlog.cn/uploads/symbian_begin.ppthttp://www.dlog.cn/uploads/symbian_env.ppt