使用DLL作为插件的设计框架
来源:互联网 发布:电信2g网络制式 编辑:程序博客网 时间:2024/05/29 14:25
在应用程序中,常常需要设计一种框架来适应需求的不断变化。经常地,在软件发布之后,用户需要增加新的功能,或者不同的用户需要根据各自特定的需求定制功能。为了达到这个目的而无需重写代码或者重做“开发——编译——测试——发布”等一系列任务,我们可以实现一种在不破坏现有代码的条件下可扩充模块的框架。使用插件(plug-in)的框架可以满足这一需要。
那么什么是使用插件的框架呢?简单地说,这种框架能允许软件在启动时查找附加的功能模块并将其与软件整合。许多应用程序,例如Microsoft Office,就使用了类似的技术来允许第三方开发者来对已有的应用程序进行扩展。怎么样来开发使用插件的框架呢?一种非常简单的方法就是使用DLL(动态链接库)来实现插件扩展。当应用程序启动的时候,在预设的目录中查找符合一定规范的DLL文件。查找完成后,应用程序使用约定好的接口调用DLL模块。
框架的生命周期如下所示:
下面给出一个C++中使用DLL作为插件的例子。1, 应用程序初始化。
2, On_Init()函数在指定的目录中查找DLL文件,例如,plug-in目录。
3, 应用程序对每个查找到的DLL调用load()函数。
4, load()调用之后,应用程序保存每个模块的名字,并对每个模块创建引用,这样,模块中的函数就可以在随后被调用。
5, 在应用程序运行的过程中,当用户选择菜单项时,相应的所定义的功能就会被执行。
6, 关闭应用程序时,调用unload()函数,用来释放load()函数中所申请的资源。
为了将问题简化,这里使用Visual Studio DLL向导创建DLL文件。创建并导出一个名为 fnPlug1的函数,参数的空,返回类型为int,如下所示。
#define PLUG1_API __declspec(dllexport)extern "C" PLUG1_API int fnPlug1(void);现在,我们来给DLL加入一个功能以便于观察到其正常工作。向你的DLL函数中加入如下代码。
PLUG1_API int fnPlug1(void){ return 1234;}
当然,在实际应用中,你需要加入特定的的功能而不是简单地返回一个数字。
为了使这个DLL文件作为插件整合进应用程序中,我们需要创建程序来进行驱动。我们的目的是找到所有的DLL文件,对其调用LoadLibrary()函数,存储HMODULE以供以后引用。下面给出一个例子。(注意我们使用.PLX扩展名代替了.DLL)
void CPluginDriverDlg::OnLoad(){ char filepath[MAX_PATH]; //who are we really? Get the Exe Path GetModuleFileName(AfxGetApp()->m_hInstance,filepath,MAX_PATH-1); SetCurrentDirectory(ExtractFilePath(filepath)); CFileFind finder; CString strWildCard = _T("*.plx"); //look for the plugin files //call this to set up the finder to iterate through all //the plugins BOOL bWorking = finder.FindFile(strWildCard); while (bWorking) { //have to call //FindNextFile() before GetFileName() or GetFilePath() //because FindFile just sets the object up and returns //true if _ANY_ files were found bWorking = finder.FindNextFile(); HMODULE hm = LoadLibrary(finder.GetFilePath()); if ( !hm ) { MessageBox("couldn't load"); } else { //loaded OK, so add each library's HMODULE to an array. //m_dwa is an MFC CDWordArray m_dwa.Add((DWORD)hm); } }}接下来,当你想要反复调用你的插件时,使用对每个插件存储的HMODULE来得到函数的地址,接着利用函数地址调用函数。
void CPluginDriverDlg::OnRunPlugins(){ for(int i=0; i<m_dwa.GetSize() ; i++) { //Find a function and use it PFUNC pFunc = (PFUNC)GetProcAddress( (HINSTANCE)m_dwa.GetAt(i), _T("fnPlug1")); if (pFunc != NULL) { int n = pFunc(); CString answer ; answer.Format("The answer is %d", n); MessageBox(answer); } }}说明一下,PFUNC的声明形式是:
最后,一定要确保做好清理工作,从内存中释放所有的DLL文件,方法是使用FreeLibrary()函数。我在测试代码的DestroyWindow()中完成了这个功能。typedef int (*PFUNC)(void);
BOOL CPluginDriverDlg::DestroyWindow(){ for (int i=0; i<m_dwa.GetSize() ; i++) { // Free all the libs we used FreeLibrary((HMODULE)m_dwa[i]); } return CDialog::DestroyWindow();}
实际上就是这么简单。你可以把任意多的插件放到预设的文件夹中;当你准备好后,执行插件中的函数。记住这是一个很简单的例子,它可以很简单地被扩充成健壮的模型,轻松载入你所需要的插件。
- 使用DLL作为插件的设计框架
- 在struts框架中使用Action作为资源的访问控制设计考虑
- 使用MFC作为共享的DLL 与 使用MFC作为静态链接库的区别
- 程序与DLL 使用 STL作为接口的问题
- 使用MFC作为共享的DLL和使用MFC作为静态链接库
- Qt使用插件的形式调用DLL
- ctk插件框架的使用
- VC之使用MFC作为共享的DLL和作为静态链接库区别
- findbugs作为Eclipse插件使用
- FindBugs作为eclipse插件和ant工具的安装、使用
- 使用Sublime Text 3作为安装 MarkDown插件的方法
- 插件框架如何设计
- c#动态编译,自己做了个c#脚本管理框架,可以作为其他应用的插件使用。增强程序的拓展性
- 使用 OSGi 作为软件产品框架
- 使用SLF4J+Logback作为Java项目的日志框架
- 在MFC的应用程序中使用插件DLL中的Toolbar
- 实战Acegi:使用Acegi作为基于Spring框架的WEB应用的安全框架
- 使用Acegi作为基于Spring框架的WEB应用的安全框架
- Linux下设置Eclipse编码为GBK进而支持中文
- intent-filter 之 data 「scheme, host, port, mimeType, path, pathPrefix, pathPattern」
- 最全的CSS浏览器兼容问题
- 函数形参数中,用double还是const double &,这是一个问题。
- LINUX系统移植(史上最全最细,强烈推荐)
- 使用DLL作为插件的设计框架
- Git学习笔记 - 1
- 配上Visual AssistX的VS2008的加强快捷键
- Android --Configuring a New Product
- 【转】备份:Android 常用 mimeType 表
- DEM数据和影像数据下载汇总
- 使用js获得元素的属性值及事件名
- UNIX System V Signals
- C#程序实现动态调用DLL的研究 (入门附代码)