Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4635810
  • 博文数量: 671
  • 博客积分: 10010
  • 博客等级: 上将
  • 技术积分: 7310
  • 用 户 组: 普通用户
  • 注册时间: 2006-07-14 09:56
文章分类

全部博文(671)

文章存档

2011年(1)

2010年(2)

2009年(24)

2008年(271)

2007年(319)

2006年(54)

我的朋友

分类:

2007-10-15 16:35:20

插件作为软件的一种扩充方式,十分的方便.做的最好的应该是Winamp的皮肤插件了,通过插件软件可以扩充自己,而扩充的部分不需要自己针对每种情况都编写代码.只要软件提供一定的接口.然后针对具体插件的代码的编写工作就交给了插件制作人员.如果你的插件提供一个公开的接口的话,那么任何一个开发人员都可以针对你的插件编写它自己的插件.下面就研究一下插件的原理.

.插件的结构.

          插件的基本结构可以用类图描述如下:

             //不好意思Word里边编辑的图片竟然在这里不能显示.                                                       

<<接口>>

IPlugin

____________________

<<接口>>

IPlugin1

<<接口>>

IPlugin2

<<接口>>

IPlugin3

 

IPlugin31

 

IPlugin32

 

……………………….

代码描述如下:

       Class Iplugin()

{

Public:

       virtual ~IPlugin(){};

       virtual const std::string & GetName()=0;

virtual const versionInfo & Geterison()=0;

virtual const void About()=0;

};

Class IPlugin1:public IPlugin

{

       Public:

              virtual ~IPlugin1(){};

              //针对这个插件的具体实现的代码

              virtual bool DoSomething1()=0;

};

Class IPlugin2:public IPlugin

{

       Public:

              virtual ~IPlugin2(){};

              //针对这个插件的具体实现的代码

              virtual bool DoSomething2()=0;

};

Class IPlugin3:public IPlugin

{

       Public:

              virtual ~IPlugin3(){};

              //针对这个插件的具体实现的代码

              virtual bool DoSomething3()=0;

};

Class IPlugin31:public IPlugin3

{

       Public:

              IPlugin31();

              //针对这个插件的具体实现的代码

              virtual dosomething31();

              virtual void About();

};

Class IPlugin31:public IPlugin3

{

       Public:

              IPlugin31();

              //针对这个插件的具体实现的代码

              virtual dosomething31();

              virtual void About();

};

从上边的结构和代码我们可以看出插件一般是通过在软件中定义一个虚函数和一定的接口,然后在插件中继承这个虚函数,实现这些接口.如果需要实现几个插件的话,那么我们只要在中间再加上一层继承层次.

 

,插件的加载

       上边我们只说明了插件的结构,并没有说明当我们已经又一个些好代码的插件,我们改如何将我门的插件的代码插入我们软件的进程空间中去.通过上边的讨论我们知道,我门的插件是由不同的人员开发的,那么就可能我们的软件发行了以后,然后才有其他人员来开发插件.通常情况下就是这样的.那么就存在这样的问题.我们知道计算机中不同的进程是运行在不同的进程空间中的.也就是我们的软件和其他人员开发的插件应该如何运行在同一个进程空间中或者如何相互交换信息.

       幸好我们知道Windows底下有一个叫做DLL的东西,它可以是我们的后来写的代码插入到一个正在运行的程序的进程空间中.同样Linux底下也有一个叫做*.so文件.它就是我们Windows底下通常知道的DLL.这样我们写的插件就可以通过一个DLL导出一个第一部分讨论的子类,然后这个子类就是实现我们插件功能的代码,也就是我们的插件.这样我们就将我们的插件的代码插入到我们的软件当中了.

示意性代码如下:

#define IPLUGINDECL _declspec(dllexport)

extern “C” PLUGINDECL IPlugin* CreatePlugin(pluginManager &mgr)

 

PLUGINDECL IPlugin* CreatePlugin(PluginManager &mgr)

{

       return  new Plugin3;

}

插件管理器

       有了插件和插件加载到软件当中去的方法后,我们还需要一个插件管理器来管理我们的插件.要不然谁来加载插件,谁来负责插件的卸载,谁来负责插件与我们软件的通信.插件管理器主要是先加载DLL:

1  HMODULE  hDll==::LoadLibrary(filename.c_srtr());

2  然后寻找插件输出的函数:

       CREATEPLUGIN pFunc=( CREATEPLUGIN)::GetProcAddress(hDll,_T(“CreatePlugin”));

       If(pFunc==null)

Findnext();

3         通过刚才我们得到的函数指针调用插件的输出函数实现我们插件的功能:

IPlugin* pPlugin=pFunc(*this);

4         插件的卸载.所需要做的工作就是从插件列表中移除插件,删除插件对象.并通过调用FreeLibrary(hDll)卸载DLL

插件与程序之间的双向通信.

       插件免不了要和我们的程序之间进行通信.要实现插件和程序之间的通信,最清晰直观的方法就是通过插件管理器进行.通过上边的代码我们可以看到在插件构造的时候我们曾经将插件管理器作为一个参数传递给了插件构造函数,这样我们就可以在插件构造的时候得到程序的数据.插件应该具有什么级别的访问能力,对程序其他部分的访问能力限制的越多,插件对程序的依赖就越小,同时插件的能力相应的就要弱一些.如果对程序其他部分的访问能力限制的越少,插件的功能可能更强一些,但是对程序的依赖就越大.如果我们以后程序有一点改变,就可能导致别人开发的插件不能使用.

       好了,到这里插件的基本原理我就理解这么多.欢迎大家指正我的不足.

阅读(1806) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-11-02 13:35:31

看了这个,有点明白了,不错!