读书人

XPCOM指南-5_施用XPCOM实用工具简化你

发布时间: 2013-01-23 10:44:49 作者: rapoo

XPCOM指南-5_使用XPCOM实用工具简化你的生活

本章回顾你已经在教程第一部分建立的代码 (see webLock1.cpp in the previous chapter) 并且使用 XPCOM 工具类让代码更容易更有效. 同时,介绍一个在XPCOM和Gecko API中广泛使用基本的字符串类型。

作为起点,第一部分描述可以替代webLock1.cpp中的很多代码的C++ 宏. 很多用来完成软件组织和组件注册的代码都可以缩减为精简的数据结构和宏代码。XPCOM指南-5_施用XPCOM实用工具简化你的生活

1. XPCOM 宏

为了让C++开发简单些,XPCOM框架提供了大量的宏。 尽管它们之间,有些重叠(例如,高层的宏可以用其他的宏来组织),他们通常可以组织成如下的类别。

1.1 通用XPCOM Module宏

前一章节,对从头创建一个常规组件要做的工作进行了详细描述。 但是输入的代码太多了,且这些代码里只有很小一部分是WebLock独有的。 怎么提高你的效率,让你在创建一个新的组件库时,只需要把代码复制过去,做较小的改动就可以重复利用呢! XPCOM提供一些列的module 宏来解决这个问题。

这些宏编译时展开为“通用”的实现,他们不会为你写你的组件提供更多的柔韧性。 他们优点在于可以让你快速开发。 这一点,你比较下面的weblock2.cpp和前一章的weblock1.cpp。

Module宏包含了一组定义NSGetModule入口点(输出函数)的宏,这需要nsIModule实现代码和为你的实现类创建一个通用的工厂。 通过使用这些宏,大多数与你组件自生功能不相关的代码可以实现(如工厂实现)。

注意,本节描述的这些宏看起来都有些相似,请仔细区分,他们适合于不同的场景。 有些宏可能只是在模块创建或销毁的时候调用了某个函数。 下表列出了本节讨论的宏。

XPCOM Module Macros

宏描述NS_IMPL_NSGETMODULE(name, components)实现组件的 nsIModule 接口,参数是组件的名字和要实现的组件的列表NS_IMPL_NSGETMODULE_WITH_CTOR(name, components, ctor)与上面宏功能一样,但是可以在模块创建后,调用传入的函数NS_IMPL_NSGETMODULE_WITH_DTOR(name, components, dtor)与第一个宏功能一样,但是可以在模块销毁时,调用传入的函数NS_IMPL_NSGETMODULE_WITH_CTOR_DTOR(name, components, ctor, dtor)第二和第三个宏的组合

模块实现宏

一般情况下,使用NS_IMPL_NSGETMODULE宏就可以了,不需要任何回调,但是所有宏都遵循相同的模式。 这些宏的所有工作都是针对components参数表示的组件数组。每一个结构描述了一个要注册到XPCOM的CID。

这些宏的第一个参数表示模块的名字。 在调试环境下,当组件加载或卸载的时候,这个字符串会打印在屏幕上。 你用该使用一个友好的名字。 下一个参数结构体包含了下面四部分信息:

人可识别的类名 类ID(CID) 契约ID (an optional but recommended argument) 对象的构造函数

1.2 通用实现宏

每一个XPCOM对象都要实现 nsISupports接口,但是一遍又一遍的写相似的实现代码真的很烦。 XPCOM提供了一些实现宏来解决这个麻烦,除非你在引用计数管理或者接口发现上有特别的需求,否则他们都是适用的。 这些宏帮你实现 nsISupports,你不需要自己写代码了, NS_IMPL_ISUPPORTS1宏实现了AddRef, Release 和 QueryInterface接口。

NS_IMPL_ISUPPORTSn为给出的类实现nsISupports 接口,并可提供数量为n的接口NS_DECL_ISUPPORTS申明nsISuppports接口的方法,包含了nRefCnt变量。NS_INIT_ISUPPORTS初始化nRefCnt为0,必须在类的构造函数里调用。NS_GET_IID返回给定名称的接口的IID。 接口必须有XPIDL生成。

使用了上面的宏, Weblock组件的代码有340行减少到不足40行。 代码更加清晰容易维护。 使用了宏的源代码参见“weblock2.cpp”。XPCOM指南-5_施用XPCOM实用工具简化你的生活

2. weblock2.cpp

下面是 weblock1.cpp的宏实现版本:

weblock2.cpp

3. XPCOM里的字符串类

字符串通常作为一个线性序列的字符集。在C++里,字符“XPCOM”有6个连续的字节组成,’X’字节偏移为0,null字符偏移为5。另一种宽字符串,使用两个字符表示一个字节,他们通常用于处理Unicode字符串。

XPCOM的字符串类,不只限于null终止的字符序列。 他们是相当的复杂,因为他们还要支持Gecko布局引擎和其他管理大数据块的子系统。 此外,Mozilla的某些版本中的字符串类还支持把序列的字符串分解为多个片段(可能或不可能是null终止的片段)。

XPCOM的字符串类都是由nsAString和nsACString两个抽象类的一个派生来的。 前面的处理双字节字符集,后面的往往使用更加平常些(使用场景更多),但着两个类都定义了字符串的相关功能。 你可以看见这些类在很多XPCOM接口中作为参数传递。 我们会在下面的章节看看这些类。

3.1 使用字符串

介绍所有的字符串类怎么工作,已经超出了本文章的描述范围,但是我们会给你展示Weblock组件里怎么使用字符串。 你首先需要注意的是字符串类没有冻结,这就意味着,当你能够避免使用他们时,就不要使用。

链接到一个完整的字符串库(.lib或者 .a)到你的组件,可能让你的组件体积增加100k(在Windows下),这在很多情况下是不能接受的(参见XPCOM string guide)。针对WebLock,使用字符串类只是用来封装已存在的字符串数据,用不着高级功能,我们其实只需要一个简单的有基础功能的字符串类。 WebLock使用的字符串类,不需要追加、串联、搜索或者其他实际的工作,仅仅是对字符串数据的封装;它们只需要能够转换为char*类型,以便作为参数传递给nsACString的相关方法。

3.2 nsEmbedString and nsEmbedCString

在本指南里使用的字符串类是nsEmbedString 和 nsEmbedCString,他们实现了nsAString和nsACString抽象类。 下面的第一个例子展现了nsEmbedCString 的用法,这里他作为不需要更改的字符串传递给某方法的nsACString 类型参数。

4. 智能指针

您目前为止看到的接口都有引用计数。 如果漏掉了释放引用计数,会导对象不能被释放,如下面的代码演示,这可能会带来大问题。

SomeClass::DoSomething(nsIFile* aFile){  if (!aFile)    return NS_ERROR_NULL_POINTER;   nsresult rv;  nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(aFile, &rv);  // ...}

如果QueryInterface 成功,localFile就非空,rv的值会被设置为NS_OK。如果失败,localFile为空,rv为被设置为相应的错误码。 这里rv是可选参数。如果你不关心它,你可以不管。完整的智能指针功能清单,参见“mozilla.org's nsCOMPtr documentation”。
Note: other-parts

1 This section discusses the main parameters of this structure. For a complete listing of all available options you can look at the complete reference in the XPCOM API Reference.

Note: nsISupports-warning

2 Note that NS_DECL_ISUPPORTS doesn't obey the general rule in which every interface has a declaration macro of the form NS_DECL_INTERFACENAME, where INTERFACENAME is the name of the interface being compiled.

Note: nulls-in-strings

3 The string classes may also support embedded nulls.

Note: other-string-classes

4 There are other abstract string classes, but they are outside the scope of this book.

读书人网 >软件架构设计

热点推荐