本文献给使用Nokia Symbian 60 SDK各个版本开发游戏软件的程序员。虽然本文主要是针对游戏软件,但是大部分内容对一般应用软件也同样适用。
1.1.声明
为了避免良心的谴责,首先我必须承认一点,我本人并不是靠Symbian C++糊口。除了forum.nokia.com上的文章和SDK,我也没有看过任何关于Symbian的书籍。只是偶然的,我在天津猛犸游戏公司(www.mammothworld.com)认识并接触了Symbian。我从零起步,写出了一个蹩脚的Symbian游戏引擎并在3650、7650上开发了一些游戏。所以我对Symbian的掌握完全是出于自己的猜测和理解,虽然本文缺乏权威,但至少都是经验之谈,容易理解。
1.2.概述
Symbian游戏是运行在手机上的游戏,它不能干扰手机正常的通讯功能,对操作系统和其它应用程序必须友善。而在首次编写Symbian C++游戏时,我遇到了无数奇怪的问题,其中大部分问题出在内存极端不足,打开太多应用程序,屏幕保护探出,接到短信、电话等特殊情况下。
其实如果养成严谨的代码风格,进行足够的错误处理,大部分问题本可以避免。为了解决它们,我很是花了一番功夫,所以在此把我的一些教训、经验写出,希望大家能避免犯同样的错误。
如果你不是业余爱好者,而是为一个认真的开发商工作,特别是如果你的产品需要通过Symbian Signed认证(www.symbiansigned.com),你就必须更加小心的对待本文提出的问题。
Symbian Signed是一个针对Symbian应用程序的认证,想要通过它,你的应用程序必须通过一系列严格的测试。认证对应用程序的文件管理、内存使用、系统事件响应、网络、资费和私人数据等都有一定的要求。如果想了解Symbian Signed认证的详细内容,可以去它们的网站下载白皮书。
1.3.异常处理
虽然我们都知道任何一个new (ELeave)或者带有L后缀的函数都可能抛出异常,但是很多业余的爱好者还是会忽视Symbian C++中异常处理的重要性。虽然有些函数只有在极其罕见的情况下才会抛出异常。但不是危言耸听,如果你不写代码捕捉并处理它们,应用程序就会遇到"系统错误"。
普通C++使用throw抛出异常。异常抛出后,栈会不停回滚,直到遇到最近一层catch为止。Symbian C++中的异常处理不使用try-catch和throw。但是它的处理机制和标准C++很是类似,区别仅仅是它只能抛出一个整数错误码,而不是一个任意对象。
我将从异常的抛出、捕捉、处理三方面讲解这部分内容。
1.3.1.抛出异常
Symbian C++中,有下面几种情况下会抛出异常:
使用静态函数User::Leave抛出异常。这个函数就是最基本的异常产生函数。下面讲的其它抛出方式都可以转化为User::Leave。
使用静态函数User::LeaveIfError把错误码转化为异常。有些函数比如CFbsBitmap::Create( )有一个TInt的返回值。如果遇到错误,这些函数就会返回非KErrNone的错误值。此时,可以使用LeaveIfError把这个返回值转化为异常。比如:User::LeaveIfError(bmp->Create(iSize, EColor4k); 其实LeaveIfError就是if (returnValue != KErrNone) User::Leave(returnValue);
使用new (ELeave)申请内存。如果没有足够内存可用,此操作产生一个KErrNoMemory异常。比如TText8* p = new (ELeave) TText8[20]; 相当于TText8* p = new TText8[20]; if (p == NULL) User::Leave(KErrNoMemory);
调用带有L后缀的函数。Symbian系统的命名规范中要求,每一个可能Leave的函数都要有后缀L。包含有带L的内层函数调用的外层函数也必须加上L。这类函数中最常见的就是NewL, NewLC和ConstructL。这个规范比你想象的要重要。因为它给其他程序员一个暗示,提示他们对这些函数进行保护。
1.3.2.捕捉异常
类似标准C++的catch语句,Symbian C++的TRAP关键字可以对一个可能产生异常的函数进行保护,并且捕获到异常值。比如:
TInt errorCode;
TRAP(errorCode, SomeDangerousFuncL( ) ); // 保护执行SomeDangerousFuncL( )函数
if (errorCode != KErrNone)
{
// 捕捉到了一个异常,在这里添加处理异常的代码
}
类似的TRAPD省去了你声明一个局部变量的麻烦。头两行代码可以简写成:
TRAPD(errorCode,SomeDangerousFuncL( ) );
1.3.3.处理异常
对于不同的异常当然有不同的处理方法(废话:-))。我们以最常见的捕获到代表内存不足的KErrNoMemory异常为例讲解。
注意在Container,AppUi等类的构造过程中,你不需要加入对内存不足的保护。因为这一切系统已经为你做好了。系统会弹出一个对话框报告内存不足。根据你的操作系统版本不同,这可能是中文的,也可能是英文或者其它语言的。如果你不信,可以在AppUi或者Container的 ConstructL中写一行User::Leave(KErrNoMemory)试试看。我试验的结果如下:
除了上面说的特殊情况,你可以简单的弹出一个对话框,告诉用户没有足够的内存运行程序,并且安全的关闭程序。比如我的游戏程序就是这样处理的:
]void CStageManager::DoGameFrame()
{
TRAPD(error, DoGameFrameProtectedL());
if (error == KErrNoMemory)
{
StopGame();
m_noMemoryDlg->ExecuteLD(R_KEY_INVALID_DIALOG);
Exit(); // Call CAknAppUi::RunAppShutter( )
}
else if (error != KErrNone)
{
User::Panic(_L("Some other error."), error);
}
}
其中noMemoryDlg是直接或者间接在Container的ConstructL中创建的:
// in header file
CAknQueryDialog* m_noMemoryDlg;
// somewhere in ConstructL
TBuf<128> errMsg;
_LIT(formater, "Not enough memory. Please close some applications.");
errMsg.Copy(formater);
m_noMemoryDlg = new (ELeave) CAknQueryDialog(errMsg, CAknQueryDialog::EErrorTone);
当然,你也可以制作一个精美的图片来报告内存不足,等待用户按任意键再退出。不过载入这个图片也可能会失败,所以至少在这个图片成功载入之前,你还是需要系统对话框来报告的。
值得一提的是,你不一定需要退出程序,或者你可以稍后重试申请内存,幸运的话,没准第二次就能成功。这是因为Symbian系统会在内存不足时自动关闭一些应用程序。我觉得这是Symbian系统一个比较奇怪的设计。通常应用程序在AppUi的HandleCommandL中会响应EEikCmdExit消息,并且调用CAknAppUi::Exit( )函数(如下代码)。这使得应用程序可以在应用程序管理器中用C键结束掉。这也使得Symbian操作系统有机会在内存不足时通过这个渠道自动关闭一些应用程序。
分享到:
相关推荐
- **服务器API**:为了便于开发者编写服务器端代码,Symbian提供了丰富的API接口,涵盖了从网络通信到数据处理等各个方面。 - **安全**:在C/S架构中,安全性尤为重要。Symbian提供了多种机制来保障数据传输的安全...
游戏代码通常包括以下几个关键部分: 1. **图形界面**:Symbian S60提供了基本的图形库,如GDI(Graphics Device Interface),开发者需要利用这些库来创建游戏画面,显示方块的移动和旋转,以及消除行的效果。 2....
在Symbian OS开发中,C语言通常用于编写底层或资源密集型组件,如驱动程序等。 - **内存管理**:C语言提供了对内存的直接控制能力,开发者可以通过`malloc`和`free`函数手动管理内存。 - **指针操作**:C语言支持...
在这个项目中,"src"目录可能包含了游戏的主要逻辑代码,而"inc"目录则存放头文件,定义了类、结构体和其他接口。这些文件是相互关联的,通过包含头文件,一个源文件可以调用另一个源文件中的函数或类。 "编译过程....
理解每种语言的特性和语法是必要的,以编写高效且可维护的代码。 5. **网络编程**:3G网络的使用意味着开发者需要掌握如何通过HTTP/HTTPS、TCP/IP等协议进行网络通信。这包括处理异步请求、错误处理、数据加密和...
这款开源游戏引擎是用C++编程语言编写的,这表明它具有高度的性能和灵活性,因为C++是游戏开发中广泛采用的语言,尤其在需要高效能计算和低级别内存管理的场景中。 "inc"目录通常包含所有头文件(.h或.hpp),这些...
程序员的角色是编写代码将这些创意变为现实,他们通常使用Java或其他编程语言。测试人员则对游戏进行详尽的测试,确保其稳定性和可玩性。最后,市场运营团队负责推广和销售游戏。 Java作为一种流行的编程语言,尤其...
在LED屏幕控制中,开发者通常需要编写驱动程序来与硬件通信,这可能包括串行通信协议(如SPI或I2C)以及理解RGB或像素阵列的控制逻辑。同时,对于实时性要求高的应用,需要了解如何优化代码以确保流畅显示。 2. **...
虽然Android底层使用C/C++编写,但大多数应用程序层代码都是用Java编写的。此外,近年来Kotlin也被广泛应用于Android应用开发中。 - **开发工具**:Android Studio是官方推荐的集成开发环境(IDE)。它基于IntelliJ ...
Lua可以用于编写辅助工具,如数据格式转换,通过调用C语言导出的函数来实现更复杂的任务。 3. **动态配置**: 在移动设备或嵌入式设备上,Lua用于动态配置,可以远程下载脚本来适应不同的设备参数。 **安装与...
- **3D游戏开发**:了解3D游戏引擎的基本架构,学习OpenGL等图形库的使用。 #### 六、软件工程与项目管理 - **敏捷开发**:了解敏捷开发的理念和Scrum框架。 - **需求分析**:学习如何有效地收集和整理用户需求。 -...
学习C语言不仅需要理论知识,更重要的是实践操作,通过编写代码来加深理解和解决问题。 此外,了解操作系统原理是嵌入式开发的关键,如进程、线程管理,资源分配等。这有助于理解硬件与软件之间的交互。对于Linux或...
这一底层主要由C语言编写,负责处理硬件驱动、内存管理、进程调度等基础功能。中间层则包含库函数和虚拟机,这些是通过C++开发的,它们为开发者提供了丰富的API接口,如OpenGL ES用于图形处理,SQLite用于数据库管理...
开发者可以使用 Qt Quick 创建复杂的用户界面,只需要描述 UI 的结构和样式,而不需要编写大量的代码。 Qt Mobile UI Offering Qt Quick 提供了一个完整的移动应用程序开发解决方案,包括了开发、测试、调试和发布...
开发人员使用集成开发环境(IDE)如Eclipse、Xcode或Android Studio来编写代码,并使用模拟器或物理设备进行测试。此外,还需要熟悉嵌入式编程语言,如C/C++、Java或Swift,以及相关的调试工具和技术。 在现代通信...
Android 一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导开发 IOS 由苹果公司开发的移动操作系统 Webkit 一个开源的浏览器引擎,在手机上的...