| Dandy's profile珠穆朗玛PhotosBlogLists | Help |
|
|
11/7/2009 Symbian 的缺陷(四)上一次的缺陷没有总结,现在补上:Symbian 中内核对象的等待机制缺少一个统一的模型。 这次要说的是过度设计上的一个例子。由于各种各样的目的,或者用户需求,应用程序在开机的时候能够自动启动是对操作系统的一个普遍要求。Windows 的全系列系统都实现了这个功能,而且具有非常丰富的支持方式。从最开始的启动组,到后来的 Run 注册表项,以及各种服务。 但是在 Symbian 上,如果你的程序没有经过 Symbian Signed,则无法达到开机自启的效果,这无疑是一个败笔。Symbian 操作系统为了所谓的安全,已经在很多地方为自签名程序(严格意义上的开发者自签名,而不是网上流行的用户自签名)设置了障碍,包括安装时的警告,以及诸多能力不可用等等。应该明白的是,开机自启并不是一个可以造成额外恶意后果的行为,而仅仅是一个程序运行的入口方式。一个程序,如果用户能够接受其手动运行时引发的影响或者后果,很显然也能接受它开机后自行启动,系统其它的安全防护措施已经保证了两种情况下程序的行为不能有能力范围上的任何区别。 与 Windows 系统作比较,即使是最新的以安全著称的 Windows Vista 系统和 Windows 7 系统,也没有彻底封杀普通应用程序将其加入开机自启列表的行为。如果说有某些开机自启行为是无法实现的话(例如受限用户安装的程序很可能仅能在此用户登录系统时才能被自动加载),那也是由于受到了另外的安全规则的制约(用户权限)。 相对而言,Symbian 系统提供的开机自启支持,不但在安全概念上逻辑混乱,而且丑陋难用,并存在不少莫名其妙的 BUG,卸载一个具有开机自启功能的软件有时会导致系统内其他具有此功能的软件自启失效(规律很难找到,似乎与文件名长度有关)。 10/29/2009 Symbian 的缺陷(三) 今天想写一个 Symbian 上的类似于 OutputDebugString 那样的函数,可以在另外的进程中接收其输出。像这样的有可能在多线程中使用的函数,毫无悬念地需要迫使你去和系统提供的同步对象打交道。 对于进程间的通知,我一直在感觉上倾向于使用 RProperty,因为它可以同时通知到所有对该属性感兴趣的进程。当然,也可以考虑 RCondVar,它也具备通知到所有等待于其上的进程的能力,但是它必须要与一个 RMutex 同时使用,不是很方便。(顺便说一下,其实一直也没太弄明白 conditional variable 的最佳使用场景,今天稍微有可点头绪,可以参看此文中的例子:http://learn.akae.cn/media/ch35s03.html) 查看 RProperty 的 Subscribe 方法时才发现,这个方法竟然没有超时设定,再去看 RMutex 等的 Wait,也一样。也就是说,我们最常用的 RMutex 对象,一旦 Wait 上去,那就只有死等,真不是一般的恐怖。不过 RSemaphore 是有的,RCondVar 也有。 一直在考虑如何使用其他同步对象实现类似于 Windows 平台的 Event 对象,目前还没有什么特别好的方案。 10/13/2009 和 CEikonEnv::ExecuteD() 相关的一个 BUG 写一个用来玩儿的 S60 小东西好久了,最近给别人安装才发现有个 BUG,退出的时候,如果开启了 ErrRd 文件,会报告 KERN-EXEC 3 错误。 调试了好几天,竟然不止一个问题,依次解决。最令人挠头的是最后一个,今晚上总算解决了。没有道理可讲的,得到的经验就是,如果你敢把 CEikonEnv::ExecuteD() 调用包含在一个 TRAP() 装置(无论嵌套了多少层函数调用)里,退出时就会发生 KERN-EXEC 3。 10/7/2009 三件小事一、前段时间曾经介绍了一下如何在 S60 上把注册资源文件和应用资源文件合并的方法,不过,这只是一种概念性的尝试,并不推荐程序员采用这种方式写程序。在我的 E66 手机上,这种方式指定的快捷方式文字是可以正常显示的,但是指定的 SVG 图标却不可以,具体原因还不清楚。在模拟器上(很是不好意思,由于测试程序过于简单,之前竟然一直没有在模拟器上跑过),连指定的文字都不能显示,而只是显示可执行文件的名字。 事实上这两种资源文件本身就存在组织格式上的差异。注册资源文件,没有 NAME(由此可知其资源的 ID 总是从 1 开始),也没有空的 signature 作为文件内容的前导,而应用程序的资源文件,则没有存在于资源文件中的 UID2、UID3 这两个信息。我相信上述的状况和这些差异是有关联的。 二、瓶子说没有使用特别能力的程序可以自签名,免受 IMEI 的限制。老汉试了试,好几个钟头没能成功,签署过的 SISX 在手机上安装老是报告“文件已损坏”,晕菜。后来才发现是生成证书的时候, dname 里有个域写错了,CO 是国家,OR 是公司,我写的时候思维跳跃了一下,把 CO 后面跟上了公司名。即便是我自己的错,也还是要说,Symbian 上有时候报告的错误真是垃圾信息,累死人不偿命。在 Nokia Forum 上我看到有人问过此问题,我几乎可以断定,是他生成的证书有问题,可惜没有一个人的回答是对路的。 三、我的 T61 小黑一直以来不能保持显示屏的自定义亮度,每次睡眠/休眠/关屏,还原之后显示器的亮度都会被系统设置为一个默认的值。在网上搜索,才知道系统在电源管理的界面里应该有和显示器亮度相关的设置,而我的系统中看不到,微软给出的解释是可能与机器的 BIOS 过于陈旧有关。我升级了一下 BIOS,没有效果。后来又看到有以下几种说法:1、与 IBM/Lenovo 的 OSD 软件有关,卸载后可以;2、与 IBM/Lenovo 的电源管理软件有关,建议不要安装。OSD 我要用,所以我宁可每次都手动调节显示器的亮度,电源管理软件则我根本没有安装。 今天上午因为别的原因,用一个软件检查了一下系统中的驱动程序状况,竟然报告有许多的驱动程序都是过期了的(由于微软有时也会告知第三方驱动程序的更新,所以原来没有太注意)。于是又把显卡驱动程序和显示器驱动程序更新了,然后就发现电源管理中出现了调节显示器亮度的选项,呵呵,不错。算是歪打正着。 8/10/2009 再说十六进制编辑器 上一次曾经介绍了一个新兴的强大的十六进制编辑器,名叫 Hex Editor Neo。该编辑器的授权使用方式为,先是全功能试用,试用期过后则退化为一个只具备基本功能的免费版。这样的软件对于一些有软件使用洁癖的人可能会觉得不是很舒服,因此本次再推荐两款十六进制编辑器,以供大家选择。 第一款叫做 HexEdit,当前免费的版本为 3.0F,主站为 http://www.hexedit.com/。它的最新版已经不是这个版本号了,但是同时也不免费了。这个软件是用 VC 写的,还使用了早期的 BCG 控件库。 第二款叫做 HxD。是个相当不错的软件,界面简洁,功能不花哨但实用,主站为 http://mh-nexus.de/en/。这个软件是用 Delphi 写的。从版权以及实用性两方面综合来看,它现在是我的首选。 7/30/2009 些许收获 折腾 Symbian 上可执行文件相关的东西好几天,一直为 ARMv5 的链接库有 lib 和 dso 两个感到困惑。有人说是 lib 是 RVCT 用的,dso 是 GCCE 用的,网上还有人说这两个要一起用,缺哪个都有问题,今天总算摸到了些门道。 其实结果很简单,lib 是为 EABIv1 模式的链接器使用的,dso 是为 EABIv2 模式的链接器使用的,无论 RVCT 还是 GCCE。如果是这样的话,lib 文件应该是某种标准的格式,我用十六进制编辑器看了,那个文件头曾经迷惑了我,典型的 !<arch> 开头,我还以为是 PE 所使用的 COFF 格式的 lib 呢,事实上 lib 里面除了一个包含有所有导出符号名字的头之外,其余的是一系列的 .o 文件(看起来都是标准的 ELF 文件)的串联。 这下我就只管 dso 了,单一文件,应该比对 lib 更好写程序去分析。 7/22/2009 有关 E32 下压缩过的可执行文件的解压问题 EKA2 上,好像可执行文件默认就都是压缩过的,不知道是不是只有 RVCT 的配置是这样,还是 GCCE 也是,没试。 很久以前我就写了个解压器,过程中要把 Symbian 写的代码改不少,这些改动随着去年的硬盘都去了。没想到眼下的项目里又要用到解压,靠,上周五、上周六、昨天和今天,大部分时间都在搞这个了。上午好不容易弄得差不多了,Debug 编译好使,Release 就会崩溃,实在是痛苦,因为这种问题是最难调试的,Release 里就是让编译器生成调试信息也不全。好在当代码运行到某个地方的时候,某一行代码触动了我的尘封记忆,直觉上这个问题我之前时遇见过的,而且问题就出在这行代码上。那是一条不起眼的内存复制语句,而我猛然想起,可能需要使用 memmove 而不是 memcpy。事实证明我是对,哈哈。 可惜好景不长,到 Symbian 下该语句会导致崩溃。为了保证代码的最大兼容性,我按照 Symbian 的 Mem 类在 Windows 下实现了一遍,把 memmove 封装到了 Mem::Move 里。现在可好,使用 Symbian 系统自己的 Mem::Move 反倒出问题,只好去查文档。乖乖,原来 Mem::Move 有很多限制,起始地址(无论目的还是源)需要在 WORD 边界上,而且长度需要是 4 的倍数,令我汗流不止。只好直接写成 memmove 了…… 6/25/2009 S60 的 Skin,一团糟 你见过这么傻的 SDK 接口么?我要在手机竖屏的时候取横屏时的布局信息,返回的结果是错误的。 错误的结果还分两类,一类是可以返回信息,而且不报错,但是数据是不正确的,这个结果我已经找到原因了,因为 S60 在横屏和竖屏这两种状态下,某些并不一致的界面元素采用了相同的 ID 值(例如竖屏下的 EStatusPaneTop 和横屏下的 EStatusPane);另一类是根本返回不了信息,原因很简单,这些元素在当前屏幕状态下不存在(例如竖屏时的 EStatusPaneBottom)。 6/22/2009 再谈 Symbian 的资源文件 Symbian 的资源文件很有趣,可能还是为了节省空间的原因,编译后的 RSC 文件里只有每个资源的内容,却没有类型。也就是说,你只能看到一个一个的块,而不知道这个东西实际上是表示什么。而且,还有压缩…… 5/15/2009 Symbian 上的资源文件问题 一、开始 不得不说,老汉是个不太安分的人,经常会做一些系统/平台不太推荐的事情。前一段时间在测试一个不使用 Symbian SDK 推荐的框架的最简化的 GUI 程序。在 EXE 里创建一个 RWindow 来显示内容并接收事件,我曾经在很久之前就写过,这次的需求略有不同,要能够在其中正常使用 CCoeControl 派生出来的控件(网上有一篇这方面的资料传播最为广泛:http://www.pushl.com/developers/exectrl.html。很不幸的是,其中有些只能用于 S60 第二版,例如涉及到的 CCoeAppUiSimple 这个类)。经过一些挫折后,总算是在模拟器里可以工作了,于是就想到真机上试试。 二、图标失效事件 要想让手机在应用程序中把程序显示出来,熟悉的开发人员都知道,需要有一个 xxx_reg.rss 资源文件。老汉在这里犯了一个很大的错误,过程是这样的。我的工程在最开始的时候,风格更接近于第二版的程序,几乎在所有的文件名种都没有 UID3 信息,中途为了更加符合三版的惯例,就修改了一次,把 UID3 加上了。最后把 SISX 部署到手机上之后发生了一个很奇怪的现象:在系统的九宫格里点击图标,不能启动程序,但是用调试器远程调试却又正常!这个问题困扰了我三四天,最终才发现竟然是忘记把 xxx_reg.rss 中 APP_REGISTRATION_INFO 结构里的 app_file 域中的可执行文件名相应地增加 UID3 而导致的。这个域很有意思,它必须与可执行文件的文件名匹配,但绝对不能写上扩展名!正是因为后面的这个限制,导致我在修改工程时误认为这个域仅仅是个描述性的文字,从而保留未动(没有附加上 UID3)! 三、显示名称事件 经过上面的修正,图标终于可以正常把我的程序启动起来了,不过另一件事情使得我的程序看起来很丑陋。图标下的文字是可执行文件名,而且毫不惊讶地,带着那个难看的 UID3!接下来的改进使我困惑:如果你想定制伴随图标显示的文字,正规的做法不是把这一信息也在 xxx_reg.rss 里指定,而是在 xxx.rss 资源文件里(一个 LOCALISABLE_APP_INFO 结构)!在 xxx_reg.rss 仅有一个链接性的信息,用 APP_REGISTRATION_INFO 结构中的两个域来描述,一个是 xxx.rss 编译后的资源文件名的 localisable_resource_file,一个是在该资源文件中包含了这一显示文字信息的结构的 ID 的 localisable_resource_id。难道我为了一个加起来不到 100 行代码的程序,竟然非要写两个 rss 文件出来? 经过仔细考察,我决定让 localisable_resource_file 指向 xxx_reg.rss 对应生成的资源文件自身。这下来了一个问题:正常的情况下,xxx.rss 在 xxx_reg.rss 之前被编译,会生成一个 rsg 文件,其中包含有 xxx.rss 中的所有资源结构所对应的 ID。这个 rsg 文件被 xxx_reg.rss 所引用,从而才可以给 localisable_resource_id 指定一个正确的值。但是现在不行了。如果我把 LOCALISABLE_APP_INFO 结构挪到 xxx_reg.rss 中来的话,那么我将无从知道资源编译器会把它的 ID 列为多少,也就无法给 localisable_resource_id 赋值。 当然,这样的困恼难不住老汉。我最终的做法是,先随便给 localisable_resource_id 写了一个数值,然后编译 xxx_reg.rss,然后找到它所生成的对应的 rsg 文件(也生成在 SDK 的 include 目录里),打开来看 LOCALISABLE_APP_INFO 的 ID 究竟成了几,然后把这个正确的数字更新到 localisable_resource_id 里,再次编译。这样就达到了一个资源文件即可满足系统所需信息的目的。 四、资源 ID 的戏法 在上面的过程中,有一件事情引起了我的注意。那些通常被我们定义时以 r_ 开头的名字命名的资源,与我们使用时所引用的对应的大写名称(其实是一个取值为数字的宏定义),究竟资源编译器是怎么生成对应关系的? 我对上面步骤所产生的 xxx_reg.rsg 文件进行了观察,看到 r_localisable_app_info(类型为 LOCALISABLE_APP_INFO)所对应的 ID(即 R_LOCALISABLE_APP_INFO)的值被定义为了 2。这不由得让我初步断定,这个值是根据 rss 文件中的 RESOURCE 定义顺序自增生成的,而且不管这个资源是否被命名了。在上例中,未命名的 APP_REGISTRATION_INFO 资源应该是占用了 1 这个 ID。带着这个结论去查看其他工程里的 rsg,得到了一个确认,一个疑惑。确认的是,ID 确实是按照前述顺序规则排列,疑惑是,这个顺序值仅占一个十六进制 DWORD 的后三位,前五位则各个 rsg 相异,不过在同一个 rsg 中总是相同的。这让我想起文档中提到的 rss 中 NAME 语句的定义不能冲突的问题,几乎可以认定这个前缀数值和 NAME 的定义值有关,但是一时找不到规律。 我写了一个批处理,来自动生成 NAME 名为 AAAA 到 AAAZ 的资源文件,并自动编译生成了对应的 rsg,可以看出前缀数值与名字一样,是一起增长的,然而准确规律依然未曾显现。不得已去 Symbian SDK 中搜索,找到了 ID 的顺序排列以及前缀数值由 NAME 变换而来的官方说法,不过并未提及变换算法。真正有价值的收获在于一个单词,offset,这是 SDK 文档中对我们前面的“前缀数值”的称谓。以此单词作为关键字到 google 上搜索,终于找到了答案,下面是经过我少些修改的变换算法代码,此工作至此告一段落。 long IdFromName(const char* name) 为了日后便于追索,把上面提到的批处理的内容也列出来(symres.bat): @echo off 5/9/2009 诡异的 Carbide.c++ 和 RVCT 组合 之前就曾经出现过这个问题,在 Carbide.c++ 中用 ARMv5 编译一个项目时,老是报告 RVCT0_0\RVCT0_0.h 找不到。 按照我的理解,应该是 Carbide.c++ 在环境变量里找不到 RVCT 的版本信息了,否则就不会出现 0_0,而是能直接找到对应的 2_2(或者 2_1)。可是 Workspace 里的另一个工程却又能正常编译,真的无法用常理解释。 Symbian 编译的诡异问题出得多了之后,我找到一个成功概率极其高的解决办法:把 SDK 的 epoc32 目录下的 BUILD 目录整个删除,然后再编译,十有八九可以搞定。 4/29/2009 S60 平台 lib 查看 在 S60 上如果用 RLibrary 动态加载其他库,那么在 Lookup 函数时就会遇到真正的痛苦,原因很简单,开发人员的手里通常只持有类和函数的名字,而 Lookup 却要求你提供一个 ordinal(此处省略鄙视 Symbian 文字约二百字)。 我们的程序在链接时也会面临这个转换过程,不过那时费力气的是那个叫做链接器的憨小子,我们只要在一旁看着就好。现在要把这部分工作手工做一遍,那就得找到函数名字和导出序号的对应表格。其实这个表格就深藏在 DLL 所对应的 lib 文件里,我们只需要一个 lib 文件的查看器就好。 可惜得很,尽管程序员往往必须关注最终用户的体验,把许多软件的界面做的越方便越好,但程序员自己所需要的工具却经常粗陋不堪,甚至能不能找到一个可用的东西都难说。你所面临的 lib 有三种,S60 第二版或者第三版的模拟器构建中的 lib、S60 第二版的设备构建中的 lib,以及 S60 第三版的设备构建中的 lib。模拟器构建中的 lib 非常好处理,微软的 dumpbin.exe 是不做二选的利器,命令行下 /exports 一下目标 lib 文件,对应关系就一目了然了。至于 S60 第三版的设备构建中的 lib,则可以借助于 GCCE 中的 arm-none-symbianelf-objdump.exe 工具或者 arm-none-symbianelf-readelf.exe 工具,对应的参数好象是 -t 和 -a -W。 最糟糕的是 S60 第二版的设备构建中的 lib,可以对它操作的貌似只能是 SDK 里自带的 GCC 中的工具,objdump.exe 虽然也在,但是输出的信息里却好像没有找到函数名与导出序号的对应关系,截至本文发表的时刻,仍然无解,敬请高手指点。 更新(上述最后一种情况的解决方案): 在网上找到了一些其他的信息,指出了导出序号其实就隐含在 objdump.exe (或者是 nm.exe)的输出信息里。前述命令可以列出 lib 中包含的一系列的 .o 文件,而文件名中的数字就是对应于函数的导出序号。 参见以下资料: 1、http://www.newlc.com/How-to-dump-DLL-exports-using-LIB.html 2、http://www.newlc.com/article.php3?id_article=453 另,得知 fontrouter 工具开源了,地址:http://code.google.com/p/fontrouter/source/checkout 4/28/2009 ELF 相关资料1、libelf:http://www.sfr-fresh.com/linux/misc/libelf-0.8.10.tar.gz/ 2、libelf 文章:http://people.freebsd.org/~jkoshy/download/libelf/article.html、http://developers.sun.com/solaris/articles/elf.html 4/14/2009 Symbian 的缺陷(二) 4、无处不在的白痴 UID3 如果你在 EKA2 下开发,那你就会发现有无数多的地方会牵涉到这个该死的 UID3:可执行文件名中有、资源文件名中有、注册资源文件名中有、资源文件资源 ID 所在的头文件(.rsg)中有、帮助文件条目 ID 所在的头文件中有(.hrh)……。 这些还好办,我们可以想办法减少影响。老汉的解决方案是,修改了 Carbide.c++ 自带的工程模板,把其中涉及到 UID3 的内容都集中到了一个 projectNameUid3.h 的头文件中去处理,然后原来各处需要使用 UID3 的文件里都包含这个头文件。这种办法尽管无法彻底消除 UID3 对工程的影响,但也还是极大地简化了移植工作(例如把这个工程作为另一个工程的起点模板)。 不过,上面既然说到了并不是“彻底”地消除,很显然还是有一些麻烦。例如,有的 XML 之类的文件,你是不能使用 #include 之类的指令向其中包含一个宏定义的。还有更糟糕的。假设你有个作用相当通用的 DLL(例如,一些常见算法的实现),这个 DLL 要在多个产品中应用。不久你就会发现这实在是一件非常痛苦的事情。首先,不能使用相同的二进制文件,如果这样做的话,第一个产品安装之后,其他产品的安装就会失败(有文件冲突,系统不知该如何取舍)。那你只好修改 UID3,并同时使用不同的文件名。多个产品安装之后,sys\bin 下就可能出现类似这样的情况:algo_0x00000001.dll、algo_0x00000002.dll、algo_0x00000003.dll。这些动态库,除了 UID3(文件名中的以及文件体中的)之外,事实没有任何不同。更不幸的事情在于,如果你所在公司的测试部经理是一个极端谨慎的人的话,他会把这些模块当做完全不同的文件来测试,他说出的话将是无可辩驳的:二进制文件不同!你很可能会由于这些问题承担来自于高层的压力,认为你在模块化设计以及代码复用方面的努力乏善可陈。 我想有人会提出内嵌 SISX 安装包的方案。我个人确实承认它是一个可以试试的办法,然而你不能忽略用户心血来潮会在安装程序列表中把它删除的风险。一旦这样,那你所有依赖于此的产品就只好统统见鬼了。 另外一个解决方案是采用静态链接库,然而很快你就会接到由客户服务部门以及其它相关部门转来的用户的抱怨,发现使用手机在网络上下载你的产品竟然需要长达半个小时!哦,天哪,产品体积实在是太大了,真是噩梦! 4/12/2009 Carbide.c++ On-Device Debugging Carbide.c++ 一直声称是支持在真实设备上调试的,昨天写了个测试程序,模拟器上运行正常,于是就编译了个目标设备版本的可执行体,并打包签名,传到了手机上。安装,没问题,运行,没反应。 于是就想在真机上调试一下。照着网上的资料做了一遍,结果老是连不到 App TRK,无论是 USB 还是 BlueTooth。折腾了很久都无法解决,于是去瓶子的机器上做个测试看,结果一连就好。排出了手机端的问题,才想到了 IDE 的差异,我的虽然也是 Carbide.c++ 2.0,但是中间升了一次级,小版本号是 2.0.2,他的仍然是 2.0.0。 今天在家里的笔记本上折腾,仍然是 2.0.2,仍然连不上。最后一狠心,把 Carbide.c++ 2.0.2 卸载后又重新安装了一遍。测试的时候,又报告“Error: TCFError: Connection type is supported, but there was an error in connecting. OSError: Could not open the device”。以为是当前的端口(COM3)和别人共用着的缘故,特意把手机占用的端口改到了 COM20,可是没有效果。网上有人说这种情况下要重启手机,正计划的重启手机的时候突然想到,会不会和我刚才开着手机上的蓝牙有关?关闭蓝牙,重新打开 App TRK,使用 USB 连上,在 Carbide.c++ 中测试一次成功。 设备:Nokia E66(S60 3rd FP1) 连接:USB 系统:Windows Vista SP1,Carbide.c++ 2.0.0 通过本次的经历,几乎可以肯定 Carbide.c++ 2.0.2 中升级过的真实设备调试组件有问题! 后记:要兴冲冲地编译目标时才发现,Windows Vista 上没有安装 RVCT…… 4/3/2009 Symbian 的缺陷(一) 今天心情好,所以再来批评一下 Symbian。其实这些问题可能 Nokia 有更大的责任,不过既然 Symbian 是基础结构么,说它也不为过。 1、纵观所有版本的 SDK,没有一个头文件里有可以标识 SDK 版本(或者操作系统版本,或者 UI 平台版本)的宏定义。 这种短视的行径长期没有得到改观。如果你想写一份在不同的 SDK 中都能正常编译的代码,简直就是困难重重。你一定想用预定义宏来区分,可是你一定会被显示撞的头破血流。一个名叫 e32ver.h 的头文件看起来好象是做这个用途的,可是打开一看你就会傻眼,里面不是宏定义,而是 const int。我想写这个头文件的工程师的大脑一定是被所谓的“纯 C++”或者“纯 OO”之类的茅草塞满了,看到宏就会下意识地写为 const int,完全不知道这些数值应该有什么用以及会怎么样被别人使用。 Nokia S60 三版的 SDK 里,include\variant 目录里有个文件,针对相关的平台定义了一系列的东西,但是,这个文件的文件名里竟然有版本号信息!这就意味着你需要分清楚 SDK 版本之后才能包含到正确的文件上,而不能达到用它来帮助你分清楚 SDK 版本的目的! 2、mmp 文件中不支持自定义库文件路径。 你没有任何办法在 mmp 文件中指定所依赖的库文件的搜索路径,尽管编译环境调用到的链接器最终无一例外都支持这一特性。LIBRARY 关键字是不支持绝对路径的,而相对路径的起点就是 SDK 的库文件所在路径。这就意味着,如果你有自己的库需要链接进来,那你就只能很愚蠢地把它们复制到 SDK 的库文件所在路径下,抱歉,也没有便利的编译后清理设施,日积月累,你的 SDK 会成为一个巨大的垃圾场。 3、愚蠢的 _LIT 宏 你想这样使用 _LIT 吗: #define STR_HELLO_WORLD "Hello, world!" _LIT(KStrHelloWorld, STR_HELLO_WORLD); 很对不住,编译器会罢工,告诉你第二参数有问题。老汉一时手痒,所以写了下面的解决方案(一个 litfix.h 头文件):
使用的时候在 cpp 中把它包含到其他所有的头文件之后就可以了。可能是由于上面已经提到过的原因,Symbian 的工程师对于宏的使用,只能算是入门级的水平。如果谁要是不相信,还可以去看看可变参数相关的那一干宏(VA_XXX)的实现,保管你不止大跌眼镜,而是大跌眼睛…… 不好意思,话题有大有小,精粗并杂,日后再整理。 未完待续。下面是不完全/不确定的目录: 4、无处不在的白痴 UID3(看它是如何影响复用的) 5、过度 OO 设计(去看看系统的消息体系吧) 6、复杂的安全模型(哦,是我见过的最安全的设计了……) 7、糟糕的模拟器(你见过它的几种死法?) 8、弱智的桌面扩展体系(Desktop/Idle/Home/Tel,随便你怎么叫他) 9、WSD 和 Cleanup Stack(已经被无数人诟病,这里提一下权当充数) 4/1/2009 WAP 中的 hidden input WAP 中中的表单支持果然如我所料,没有愚蠢到竟然不会想到有人需要一个不可见的 名字-值 对,就像 HTML 中的 hidden 元素似的。今天查到了,是一个叫做 postfield 的标签,长的是这个样子:〈postfield name="name" value="value"/〉。 3/28/2009 FAULT KERN: 8 写的一个程序,在模拟器里调试的时候发现,在 S60 第三版上什么事也没有,可是在第二版上就会出问题。它本身是可以运行起来的,可是一旦启动别的应用,如 Messages 或者 Services,模拟器就会死掉,有时候会显示一个“FAULT KERN: 8”的对话框。 也曾经研究过它,注掉了绝大部分代码也没有起色。今天又咬了咬牙,最后才发现,问题出在我怎么也想不到的三行代码上: RProcess me; me.SetProtected(ETrue); me.SetSystem(ETrue); 这只不过是二版上对进程的简单保护措施而已,模拟器竟然不买账,可怜我一直以为是 WindowGroup 及其焦点切换时的处理有问题,晕死…… 3/26/2009 有关重定位的资料 去年写 Symbian 可执行文件的解压器的时候,自己曾研究了一段时间相关的东西并写了总结文档,可惜硬盘毁于一旦后就什么都没了。以下链接可供参考:http://blog.csdn.net/xuplus/archive/2008/04/15/2293594.aspx |
|
|