引言
目前,不少流行软件都提供有对外挂插件的支持功能,如Winamp、Realplay等等。这些软件通过对插件技术的使用为日后的软件升级和功能扩展提供了相当的便利条件。 尤为重要的是,通过使用插件技术,使得对软件的功能扩展将不再完全受限于软件厂商,任何第三方开发商或是程序员个人只要遵循了软件提供的插件接口标准去开发插件就完全可以同主体软件有很好的兼容,从而使用户对应用程序进行个性化功能扩展成为了可能。基于插件技术的以上诸多优势,本文下面将围绕插件的制作、应用程序对插件的支持等具体问题对其展开讨论。
设计思路及插件接口标准
通常支持插件的应用程序多将外挂扩展插件集中放置于某个指定的目录下,程序执行时首先在此目录下搜寻是否有插件存在,如有则为插件将其插入到应用程序,应用程序在终止运行时负责将插件释放。
至于插件以何种形式提供则没有固定的规定,可以是独立的应用程序,也可以是动态链接库或是其他一些文件格式,不管插件具体以何种形式提供,都是以方便使用为目的。本文即以使用较为灵活的动态链接库作为插件的提供形式,动态链接库通过外部导出函数为应用程序提供对插件功能的调用,应用程序在对动态链接库进行动态装载时也比较容易实现。这里与以往对动态链接库的使用有所不同,通常的应用程序事先已经明确知道需要使用哪些动态链接库,动态链接库又提供有哪些函数等信息,而允许使用插件的应用程序在发布时则无法预知在软件发布后第三方开发商将会开发出多少插件、插件都提供有什么功能函数等。因此这就需要在容许插件的应用程序和插件之间建立一种统一的接口标准并通过此接口标准完成对所有后期插件的管理。在此,主程序和插件之间是通过一个标准的DLL导出函数来实现的,主要用于在主体程序内插件对象的创建:
BOOL Plug_CreateObject(void ** pobj) { *pobj = new CPlugA; return *pobj != NULL; } |
class CPlugBase { public: CPlugBase(){}; virtual HICON GetIcon() = 0; virtual void Interface(int k) = 0; virtual void Release() = 0; }; |
typedef struct{ CPlugBase * pObj; HINSTANCE hIns; }PLUG_ST, * LPPLUG_ST; |
另外,在程序界面上,每向应用程序添加一个新的插件,都应当在主程序的界面上增添与之相关联的按钮或菜单等,以便用户可以通过位于主程序界面上的按钮或菜单实现对插件内部功能函数的调用。本文在此是通过向工具条增添按钮的方式来达到此目的的,按钮上的图标由插件提供,应用程序通过插件类的GetIcon()函数获取到图标句柄,并将其绘制在工具条按钮上。
为普通应用程序扩展插件支持功能
插件支持功能并非Winamp、RealPlay等大牌软件所独有,任何普通应用程序经过程序编码均可将其扩展为支持插件的应用程序。通常将这部分扩展代码在主框架类中完成,根据前面所述思路,首先从应用程序所在目录下搜寻子目录PLUGINS下是否存在以动态链接库形式提供的插件,如果在此目录下没有找到动态链接库那么就说明当前还没有插件,因此程序也就不需要做进一步处理,如果找到插件,就一一将其插入到应用程序。搜寻插件的部分代码如下: