SCIM输入法架构分析.doc_第1页
SCIM输入法架构分析.doc_第2页
SCIM输入法架构分析.doc_第3页
SCIM输入法架构分析.doc_第4页
SCIM输入法架构分析.doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

SCIM输入法架构分析(上)开发者在线 B 更新时间:2007-12-26作者:absurd 来源:CSDN本文关键词: 架构分析 输入法 SCIM转载时请注明出处:/absurd/ 文档格式与术语说明 1. 概述SCIM是Smart Common Input Method的简称,它是一个输入法框架,由苏哲领导开发的。作为新一代输入法框架,其架构设计精良,具有很好的扩充性和灵性性,代码质量也非常高,称得上是国内经典的开源项目了。本文试图对SCIM的架构进行分析,了解它的架构,也许并不能帮助你更好的使用它,但对于添加新的输入法引擎,或者把它移植到其它平台,会有一些帮助。不过,即使单从学习的角度出发,了解它的架构,对于提高设计能力也是有很大好处的。 SCIM具有如下特点:1. 完全面向对象的设计,并用C+实现。2. 高度模块化。3. 非常灵活的设计,支持动态加载不同的输入法,支持C/S模型运行。4. 简单的编程接口。5. 对UNICODE提供全面支持。6. 提供了一些非常好用的工具函数,可以大大加快开发进度。7. 提供了功能丰富的GUI panel。8. 提供了统一的配置框架。9. 很方便的集成现存的输入法。10. 不但支持传统的键盘输入法,也支持手写识别等新式输入法。 2. SCIM的组成部件l 配置模块(Config)l 输入法前端模块(FrontEnd)l 输入法引擎模块(IMEngine)l 进程间通信模块(IPC)l 输入法Panell 输入法Helper SCIM是高度模块化的,每个模块都非常独立。为了做到这一点,一方面需要从设计出发,让各个模块完成单一的功能,使模块本身是高内聚的。而另一方面,SCIM也采用了几种高级的技术:l 针对接口编程。对于一些具有不同实现的模块,为了减少与调用者的耦合,提供一个抽象的接口是有必要的。配合下文所介绍的动态加载机制,模块的调用者根本不关心采用的哪种实现,接口与实现是分开的,它使用的是模块的抽象接口,模块的实现变化时,对模块的使用者几乎没有影响。l 模块动态加载机制。SCIM的整个设计干净利落,框架就是框架,其它任何附加的功能都是通过插件来实现的,在运行时才动态的加载进来。不同的平台对于动态库的处理方式有些不一样,SCIM实现了一个module类,对操作系统的底层函数进行了封装,同时提供面向对象的接口,使用更加方便。l signal/slot机制。多个不同的对象协作起来完成一项任务,是面向对象设计的特点之一。消息在这些对象之间来回传递,特别是对于异步调用、事件/状态触发等情况,底层模块需要调用上层模块中的函数。这样,模块之间的层次关系不再像面向过程中那样明显。凡事有利必有弊,如果设计得不好,可能会造成上层与下层之间紧密的耦合,层次关系混乱。为了避免这个问题,SCIM里采用了signal/slot机制,上层向下层注册signal的处理器(slot)。当某个signal触发时,下层模块回调signal的处理器(slot)。 下面我们一一分析各个模块。2.1. 配置模块(Config) 所谓众口难调,再好的软件也无法满足不同用户,不同的环境下的需求。采用配置文件来定制软件,是惯用的手法。SCIM也不例外,但是作为输入法,也有其特殊性,多个应用程序(如Panel、输入法服务进程、手写、输入设置界面等)往往要共享一些配置信息。 如果这些应用程序都直接去操作配置文件,不但可能会发生访问冲突,导致配置文件被破坏。也可能出现配置不同步的情况,一个应用程序修改了配置信息,而其它应用程序毫不知情,无法让配置信息在所有相关进程中即时生效。 最好的办法是,所有的配置信息由一个应用程序负责统一管理。只有它能够直接存取配置文件,其它应用程序,都需要通过向它发送请求来存取配置信息。这样,以上几个问题都迎刃而解了。 无论直接存取配置文件,还是从其它进程中存取配置信息,对使用者来说,并不需要关心。也就是说,使用者关心的是接口提供的功能,而不关心具体的实现,实现改变后,也不应该影响使用者。为了让各个应用程序采用统一的方式存取配置信息,SCIM中定义了一个ConfigBase接口,使用者通过它存取配置信息。 由此可见,SCIM中的配置模块有不同的实现,这些实现都要求遵循ConfigBase接口规范。SCIM提供了两个默认的实现,它们都是作为动态可加载模块形式出现的。一个称为SimpleConfig,它是用来直接存取配置文件的,另一个称为SocketConfig,它是用来从输入法服务进程存取配置信息的。 2.2. 输入法前端模块(FrontEnd) 个人认为,输入法的前端(FrontEnd)这种说法容易让人误解。按常识讲,相对后端而言,用户直接打交道的才称为前端,我开始以为前端就是Panel。其实不然,输入法是作为一个服务进程来实现的,这里的前端是指输入法服务进程中接收请求的模块。它负责接收来自客户端应用程序的请求,把请求转发给具体的输入法引擎或者配置模块,最后把处理的结果返回给客户端应用程序。 SCIM中的前端也有不同的实现,这些实现都遵循FrontEndBase接口规范。SCIM提供了两个默认的实现,它们都是作为动态可加载模块形式出现的。一个称为SocketFrontEnd,它定义了一套自己的通信协议,当然这协议是属于应用层的,它下层协议通常采用本地socket,但它并不限于某种特定的承载层。客户端应用程序必须遵循这个协议,把请求按这个格式发上来,它就可以使用SCIM提供的服务。另外一个是基于XIM实现的,这是一种X Window提供的老式输入方式,似乎一般很少使用。 2.3. 输入法引擎模块(IMEngine) 输入法引擎就是输入法的具体实现,比如拼音输入法,五笔输入法等等。不过在这里,输入法引擎其实是一个抽象的概念,可以是一种输入法,也可以是多种输入法,甚至只是一个输入法的代理。前面说过,SCIM只是一个输入法框架,其它输入法要挂到SCIM里来,就需要实现一个输入法引擎。 毫无疑问,SCIM中的输入法引擎也有多种实现,这些实现都遵循IMEngineInstanceBase接口规范。SCIM提供了两个默认的实现,它们都是作为动态可加载模块形式出现的。一个称为SocketInstance,它是一个输入法代理,一般来说,应用程序直接使用的就是它。另外一个称为RawCodeInstance,顾名思意,就是将按键原封不动的输出。 其它输入法要挂到SCIM框架里来,需要实现IMEngineInstanceBase接口,并编译成一个动态库,放在指定的目录之中。所以SCIM并不与某种具体的输入法关联起来,而运行时动态加载进来的。其它输入法不在SCIM的核心之列,都是以单独的软件包发行的。 2.4. 进程间通信模块 输入法所服务的不是一个应用程序,而可能是系统中所有的应用程序。若把它作为应用程序的一部分来实现,会造成不必要的数据冗余,浪费硬件资源。作为一个单独的服务进程是合适的,用C/S模型来实现。所以进程间的通信机制必不可少,SCIM采用的本地socket方式,当然也可以用其它方式实现,但没有什么必要。 应用层协议封装在Transaction中,它负责把特定的请求或事件等打包成数据包,也负责从数据包中取出请求或事件等。至于数据的实际传输,由Socket实现。服务器端使用SocketServer,客户端使用SocketClient。Transaction使用的是Socket的抽象接口,并不关心是服务器端还是客户端。 2.5. 输入法Panel 对于输入法来说,Panel是必不可少,若没有它,再好的输入法也是没有点睛之笔的作品。Panel不但给用户一种直观的反馈,如候选字,联想词组等,也提供了一些辅助功能,如中英文切换、全角半角切换,查看帮助信息等。 但是Panel是有GUI界面的,也就是说,Panel必须要与特定的GUI绑定起来,SCIM是一个输入法框架,应该尽量不要依赖于特定的平台。这一点上,SCIM做得很好,尽管SCIM实现了一个基于GTK的Panel,但它并不属于核心之列,它是一个完全独立的工具。 不管用哪一个GUI实现Panel,有很大一部分代码都是相同或者相似的,SCIM把这些代码封装在两个类中,一个PanelAgent类供Panel的服务器端使用,Panel本身通过它接收请求。另一个PanelAgent类供Panel的客户端使用,用它来与Panel进行交互。 2.6. 输入法Helper 一些新的输入法方式,如手写输入法等,当作传统的IMEngine来实现,比较麻烦也不太优雅。SCIM把这些输入法作为特殊处理,通过Helper集成进来。 SCIM提供了一个HelperAgent类,手写输入法通过它把手写结果提交给应用程序。HelperAgent实际是Panel的一个客户端,它与PanelAgent交互,但是它的功能很简单,而且与PanelClient功能并没有太多相似之处,所以作为一个单独的类来实现。SCIM输入法架构分析(下)开发者在线 B 更新时间:2007-12-26作者: absurd 来源: CSDN本文关键词: 架构分析 输入法 SCIM转载时请注明出处:/absurd/ 1. 概述SCIM是Smart Common Input Method的简称,它是一个输入法框架,由苏哲领导开发的。作为新一代输入法框架,其架构设计精良,具有很好的扩充性和灵性性,代码质量也非常高,称得上是国内经典的开源项目了。本文试图对SCIM的架构进行分析,了解它的架构,也许并不能帮助你更好的使用它,但对于添加新的输入法引擎,或者把它移植到其它平台,会有一些帮助。不过,即使单从学习的角度出发,了解它的架构,对于提高设计能力也是有很大好处的。 2. SCIM的组成部件2.1. 配置模块(Config)2.2. 输入法前端模块(FrontEnd)2.3. 输入法引擎模块(IMEngine)2.4. 进程间通信模块2.5. 输入法Panel2.6. 输入法Helper (续)2.7. 模块动态加载机制(Module)SCIM只是一个框架,具体的输入法是通过动态库的方式加载进来的,而不是在编译时静态的绑起来的。SCIM实现了一个Module类,封装了操作系统底层函数,提供面向对象的接口。另外,在此基础之上,还实现了其它几个类对Module进行包装,提供更具体的服务。 ConfigModule 用于动态加载配置模块。FilterModule用于动态加载过滤器模块。FrontEndModule用于动态加载前端模块。IMEngineModule用于动态加载引擎模块。HelperModule用于动态加载辅助功能模块。 2.8. 其它组件2.8.1. 过滤器(Filter)模块:提供动态的转换或过滤功能,可以实现诸如在中文繁体和简体之间进行转换的功能。2.8.2. 异常处理:SCIM完全采用OOP编程,使用了C+的异常处理机制,大部分模块都有自己的异常处理类。2.8.3. 类工厂:为解耦使用者与实现者之间的耦合,SCIM采用了类工厂的机制来封装对象的创建。2.8.4. Signal/Slot:为解耦软件各层间的耦合,SCIM采用了Signal/Slot机制。 3. SCIM的动态行为(GTK+中)3.1. 传统输入法 PanelClient/ SocketInstance/SocketConfig是在应用程序进程中运行的,但为了降低与应用程序的耦合,它们往往被封装在一个独立的模块里,比如在GTK+中就是这样做的。 Panel是作为一个单独的进程运行的,它通过PanelAgent与外界交互。 输入法服务进程也是一个单独进程,它通过SocketFrontEnd与外界交互。尽管它也可以是另外一个输入法服务进程的代理,不过那样做似乎没有什么意义。3.2. 手写输入法 手写输入法不是作为一个普通的引擎来实现的。它往往是一个单独的进程,带有GUI界面。它通过HelperAgent把识别的字符串提交给Panel,或者转发一些事件给Panel,它与应用程序之间并无直接通信。 Panel在此时除了具体传统的功能外,同时还作为手写输入法与应用程序的中介者。 这里的应用程序和普通的应用程序没有差别,它根本不会觉察到手写输入法的存在,这可能也体现出SCIM设计的精妙之处吧。 4. SCIM框架与具体输入法的关联具体的输入法要挂到SCIM中,那是一件非常简单的事情,只要实现IMEngineInstanceBase接口,编译成一个动态库,放到指定的目录即可。输入法的实现者不必花费时间去考虑如何与应用程序关联起来,专心的去实现输入法本身就行了。 5. SCIM与GTK+的关联GTK+是GNOME的一套GUI,实现得也很精致。把输入法挂到GTK+中来很简单,和SCIM类似,它对输入法也作了抽象,它要求实现GtkIMContextClass接口,并编译成一个动态库,放到指定的目录即可。 关于GtkIMContextClass的描述,可能参考文档/doc/API/2.0/gtk/GtkIMContext

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论