Plug-in插件技术

 

1 什么是插件?

插件是在不改动主体程序的情况下给主体程序增加功能的软件。

 

>> 插件是软件产品,能够完成一定的功能

>> 一般来说,插件不能独立运行,它是作为主体程序的辅助模块来工作的

>> 支持插件是软件程序为自身提供可扩展性的流行手段之一,因此现代的很多软件都支持插件技术

 

我们比较常见的支持插件的软件有:

软件名称

与插件技术相关的部分

PhotoShop

这个2D图像专业处理软件中提供的各种滤镜都是通过它的插件实现的

Winamp

这个著名的音频播放软件中的音频解码、DSP处理、音频播放、VISML这些功能也都是通过插件实现的

Emacs

这个Linux下非常流行的文本编辑软件中的很多功能都是用LISP语言写的一段脚本,这些扩展功能用的脚本也是插件

MS-Word

这个微软的重量级文字处理软件中很多扩展功能都是通过宏来实现的,这些宏模块也是插件

Gaim

这个Linux下的通用即时聊天工具可以同时支持MSNYahooICQQQ等多种聊天协议,也是通过插件来实现的

 

2 插件是如何实现的?

 

关键字:插件工作机制,插件协议,插件接口

 

那么,插件是如何在不改动主体程序的情况下给主体程序增加功能的呢?是不是所有的程序都可以在不被改动的情况下得以扩充功能呢?要回答这两个问题,就需要了解插件的工作机制。

 

我们把PhotoShop和它的各种滤镜的关系作一个简单的描述,这个问题的答案就清楚了。

 

首先运行PhotoShop,我们会看到它启动的过程比较复杂,需要加载很多东西。其中有一个启动步骤是在某个目录下寻找某种文件,这些文件中的程序就是它的滤镜。PhotoShop会对找到的每一个这样的文件进行一个测试,测试通过则认为它的确是一个滤镜程序,否则将放弃对这个文件的加载。

 

之后PhotoShop根据所有通过测试的滤镜的相关信息修改自己的菜单,为每一个滤镜在其中添加一项。

 

PhotoShop准备就绪后,用户打开某张图片然后选择了滤镜菜单里的某一项后,PhotoShop会把这个图片的相关数据和信息按照规定好的格式传递给与此菜单项对应的那个滤镜程序,让它来处理,此滤镜处理完成后,把结果按照规定好的格式传递给PhotoShop,由PhotoShop来做后续的处理。

 

每一次滤镜处理PhotoShop都重复这一过程,对于不同的滤镜,处理图像的结果可能不同,但对于PhotoShop来说所有的滤镜都是相同的,都是通过这样一个过程对图像数据进行了变换。

 

这就是PhotoShop和它的滤镜通过协作来完成某个功能的过程,它经过了极大的简化,但足以说明问题,我们可以得到以下结论:

1>对于主程序来说,插件可有可无,主程序只是在运行过程中的某些特定的情况下才去加载某个插件。因此插件工作的第一阶段是加载。

 

2>主程序加载某个插件的时候需要做某种测试,以确定它的确是一个插件。因此插件工作的第二个阶段是接受测试。(有些类型的插件没有这个阶段)

 

3>在插件加载并测试成功后,主程序和插件之间会按照某种规定进行数据交互,以完成特定的功能。因此插件工作的第三个阶段,也是主体功能阶段是进行数据交互和数据处理。

 

从以上的3点我们可以清楚地感觉到,插件工作的每一个过程都要求严格地遵循某种规定。这个规定我们称之为插件协议,或者插件接口,它是由主体程序规定、并由插件程序遵循的。插件协议包括三个方面(和以上的3点相对应):

 

1>插件如何被加载。

 

例如插件文件应该放在哪个目录下,文件的名字应该符合怎样的特征,插件应该在哪个文件里添加怎样的信息等等。

 

这一点保证了主体程序在加载插件的过程中能够成功地找到插件程序,这是第一步,非常重要。如果某个插件没有按照规定去做,主体程序将不会发现它的存在,更不可能去加载它。

 

2>插件必须提供的主接口。

 

如果主体程序要求插件程序以动态连接库的方式提供,那么主体程序一般会要求插件程序导出一个函数,函数名、函数参数、函数返回值类型必须与规定一致,这个函数将作为插件的主接口。

 

主体程序会在加载插件后,立即寻找它导出的这个接口函数,如果找到将调用它并完成一些初始化工作,如果找不到,则认为此插件没有遵循协议,不是一个正确的插件,同时放弃对它的加载。

 

这一点提供了插件的合法性验证,为后续更有意义的功能实现提供了保证,这非常类似于很多网络协议的握手过程。

 

3>插件的功能性接口。

 

这是插件完成其功能的主体接口,可以只有一个,也可以有很多,依据此类插件的共同特征而决定。这些接口同时也规定了数据交互的具体格式。

 

插件在实现时,可以实现所有这些接口,也可以有选择的实现某一个合理子集。

 

现在,我们可以回答这个问题了,插件是如何实现的?简而言之,插件是通过实现主体程序定义的插件协议实现的。

 

插件机制首先是由主体程序制定插件协议,并在其自身内实现对这个协议的支持,然后由第三方按照此协议实现一个功能模块,最后当主体程序和此模块共同协作时,模块的功能得以实现,主体程序也因此得以扩展。

 

3 插件分类,不同类别的协议,以及采用此类协议的著名软件

 

支持插件的软件及其插件可以按照他们使用的插件协议分成几个大的类别。

 

1>使用动态连接库提供简单的导出函数

 

此种类型的软件采用的插件协议依赖于操作系统提供的动态连接功能,一般要求在库中导出一个函数,通过调用此函数返回一个结构体的指针,而此结构体的成员大多是一些函数指针,通过指针对这些函数进行调用可以得到与此插件相关的信息或实现此插件提供的功能。

 

比如定义一个结构体

typedef struct InterfacePlugin

{

 const char* (*pWhoAreYou)();

 int (*pDoYourJob)();

}InterfacePlugin, *pInterfacePlugin;

 

再定义一个函数

PInterfacePlugin GetInterfacePlugin();

 

主体程序首先加载动态连接库,然后在其中寻找名为GetInterfacePlugin的函数的入口地址,如果找到则调用它并得到返回值ret,通过这个返回值,可以进一步调用ret->pWhoAreYou得到与此插件相关的信息,或调用ret->pDoYourJod来让此插件实现它的功能。

 

这种类型的插件接口无论对于主体程序还是插件程序,都非常的简单,易于理解,易于实现。

 

这种类型的典型软件就是Winamp

 

Winamp提供了解码、播放、DSPGeneralVISML等多个插件接口,每一个接口都是一个这样的简单协议。

 

因此大家不难发现,接口虽然简单,但它能提供的扩展性却非常强大,Winamp插件的丰富多彩和Winamp的流行足以证明这一点。

 

2>使用动态连接库,但提供复杂的导出函数,导出函数返回的接口结构体一般不独立,而是和其他众多插件模块的接口有着各种关联。

 

这种类型的插件实现的接口一般从某个接口体系中继承而来,主体程序还会提供所谓的插件管理器。

 

因此,此种类型的某一个插件可能并不复杂,但它总是在某个继承体系中,整个体系的结构和内部关系总是复杂得多。

 

这种类型的插件接口可以提供非常强大的数据交互过程,适用于数据处理过程很复杂的场合。

 

这种类型的典型软件有PhotoShop

 

如果你去看一看PhotoShop的插件接口手册,刚上手的话,估计把各个接口的关系理解清楚就要费半天劲,再去写个实际的插件拿去用就得再费些功夫了。

 

3>使用COM技术。

 

这应该是微软的专利了。

 

我们这里用IEBHO的插件协议来说明。

 

首先你的插件应该是一个COM组件,然后你的COM组件至少得从某个接口继承并实现它的虚函数,如果你需要得到更多的控制权,则你可以根据需要再从其它接口继承,最后的结果是一个多继承的子接口COM组件。

 

然后你需要按照BHO的规定在注册表的某个地方创建子键,写入键值,以此来通知IE你为它添加了一个COM插件。

 

如果没有错的话,IE就会在下次打开时加载你的组件,并通过IUnknown接口查询你实现的各种接口,并在适当的时候调用某一个接口的某个函数。这样IE的功能就得到了扩展。

 

这种类型的插件需要你了解COM技术、注册表、Windown消息机制以及你可能用到的各种各种Windows系统机制。

 

显然,这种类型的插件也是复杂的,但由于它采用了COM技术,因此几乎能从一个IUnknown得到你想得到的其他任何接口,访问它们和它们维护的数据。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值