简介
QT 到 S60 的移植是基于 native Symbian OS 和 Open C 完成的,如下图所示:
 |
| 来自资料1 |
QT/S60 GUI 应用与 S60Main 静态链接。S60Main 为 QT/S60 应用程序实现了
Symbian OS 入口函数 E32Main()。这与 Open C libcrt0 类似,libcrt0初始化环境
并调用 QT 使用的标准 main() 入口函数。libcrt0 和 S60Main 的区别在于
S60Main 初始化标准 S60 UI framework,而 libcrt0 仅仅初始化非 GUI 应用
需要的服务。事实上,无论什么时候 QT 的入口点函数 main 被调用,标准 S60
UI framework 的类如 CAknApplication, CAknDocument 和 CAknAppUI 已经被
实例化了,主线程的 control environment (CCoeEnv) 和 active scheduler
(CActiveScheduler) 也存在了,这就可以将上层的 QWidget 和 native
control 集成起来,使 QT widget 使用 native 输入法,即 Front End
Processor(FEPs)。注意,非 GUI QT 应用仍然是与 Open C libcrt0 链接,而
不是 S60Main。
Qt for S60 已经发布了一个版本,叫"Garden",已经移植的 QT 库包括
QtCore, QtNetwork, QtScript, QtGui (部分), QtScript, QtSvg, QtTest 和
QtXml。倚赖库如下表所示。
| Library |
Description |
| libc(Open C Libs) |
Basic C programming routines: basic types, sockets, I/O, process, etc |
| Libm (Open C Libs) |
Mathematical functions |
| Libdl (Open C Libs) |
Dynamic loading and symbol lookup |
| libpthread |
POSIX standard interface for multiple threads |
| libssl |
Implements SSL v2/v3 and TLS v1 protocols |
| libcrypto |
Provides services for OpenSSL |
| Euser (Symbian Libs) |
Basic Symbian OS types and services: active scheduler, etc |
每个 QT 模块的移植细节
在移植过程中,QtCore 的进程管理(process handling)、文件系统监视器(file
system watcher)和事件分发器(event dispatcher)等模块针对 Symbian 系统做
了定制。
- 由于 Open C 库的限制,进程管理(process handling)部分的代码被重写:
src\corelib\io\qprocess_symbian.cpp;
- 出于性能考虑,文件系统监视器(file system watcher)被重写:src\corelib\io\qfilesystemwatcher_symbian.cpp;
- 事件分发器被重写,以集成 Symbian OS active scheduler 和 POSIX
select based event dispatchers:
src\corelib\kernel\qeventdispatcher_symbian.cpp。
由于本地文件系统被监视,在 QtCore 的实现中使用了 Symbian OS file
server(efsrv) 库。为了实现线程相关的类,QtCore 也链接了 Open C pthread
库。
由于 Open C 的限制,QtNetwork 的网络接口针对 Symbian 系统做了修改,依
赖于 insock 和 esock Symbian OS 库。
为了支持 SSL,使用了 Open C 的 libssl 和 libcrypto 库。
QtGUI 也针对 Symbian/S60 系统修改了 GUI 相关的类。QT GUI 模块与 S60 集
成的结构图。
 |
| 来自资料1 |
QT 使用了很多设计技巧分离平台相关的代码实现,如 private 实现模式。由于
这些技术的使用,移植后 QT API 没有任何改变。如前所述,进入 QT main 应
用程序入口点之后,S60 UI framework 被实例化。当应用程序创建了一个
QAppllication 实例后,S60Data 对象被初始化。这个对象包含了保存 S60Main
创建的 S60 UI 相关对象的指针,这些对象包括 RWsSession、RWindowGroup、
CCoeAppUI 等等。
每个上层的 widget 使用 QSymbianControl 创建一个 native control(CCoe)。
通过 CSymbianControl,widget 收到不同的事件,将它们分发给子 widget。
QSymbianControl 也像一个介于 S60 FEP 和 QT 输入上下文之间的 proxy。
Widget 将自己绘制到 S60 平台独有的 widget surface 上,它实际上是一个
CFbBitmap,但只能通过 QImage 接口访问。从 QT 看,CFbsBitmap 是一个
后台 paint device,往屏幕上显示时,QS60WindowSurface 会通知 QSymbianControl 将 CFbBitmap 的数据 bitblit 到 CCoeControl 提供的窗口图形上下文中 (CWindowGC)。
分离 QT 和 S60 代码
S60 代码应该与 QT 代码分离,以便于不同平台的移植。private
implementation 是 QT 常用的策略,不同的平台有不同的 private 类实现。
QtS60AOExample 有一个 wrapper 类,它有 S60 平台的 private
implementation。private implementation 的原理如下所示。
public class 的成员是指向 private class 的指针。
AOWrapper::AOWrapper(QObject *parent)
: QObject(parent)
{
d_ptr = new AOWrapperPrivate(this);
}
public class 的指针作为 private 类的构造函数的参数。
AOWrapperPrivate::AOWrapperPrivate(AOWrapper *wrapper)
: q_ptr(wrapper)
{
}
private 类的 q_ptr 成员指向 public class,public class 的 d_ptr 成员指
向 private class。
Reference
- Qt in the S60 environment
- Open C/C++ in the S60 platform architecture
|