Port QT to S60 Policy
作者: 刘鹏
日期: 2009-05-15
QT 已被移植到 S60 平台上,文本介绍了总体思路和各个模块的移植细节。

简介1

QT 到 S60 的移植是基于 native Symbian OS 和 Open C 完成的,如下图所示:

来自资料1
来自资料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 模块的移植细节1

在移植过程中,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
来自资料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 代码2

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

  1. Qt in the S60 environment
  2. Open C/C++ in the S60 platform architecture