在应用程序中,常常需要设计一种框架来适应需求的不断变化。经常地,在软件发布之后,用户需要增加新的功能,或者不同的用户需要根据各自特定的需求定制功能。为了达到这个目的而无需重写代码或者重做“开发——编译——测试——发布”等一系列任务,我们可以实现一种在不破坏现有代码的条件下可扩充模块的框架。使用插件(plug-in)的框架可以满足这一需要。

那么什么是使用插件的框架呢?简单地说,这种框架能允许软件在启动时查找附加的功能模块并将其与软件整合。许多应用程序,例如Microsoft Office,就使用了类似的技术来允许第三方开发者来对已有的应用程序进行扩展。
        怎么样来开发使用插件的框架呢?一种非常简单的方法就是使用DLL(动态链接库)来实现插件扩展。当应用程序启动的时候,在预设的目录中查找符合一定规范的DLL文件。查找完成后,应用程序使用约定好的接口调用DLL模块。
        框架的生命周期如下所示:

1, 应用程序初始化。

2, On_Init()函数在指定的目录中查找DLL文件,例如,plug-in目录。

3, 应用程序对每个查找到的DLL调用load()函数。

4, load()调用之后,应用程序保存每个模块的名字,并对每个模块创建引用,这样,模块中的函数就可以在随后被调用。

5, 在应用程序运行的过程中,当用户选择菜单项时,相应的所定义的功能就会被执行。

6, 关闭应用程序时,调用unload()函数,用来释放load()函数中所申请的资源。

下面给出一个C++中使用DLL作为插件的例子。
        为了将问题简化,这里使用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 PathGetModuleFileName(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 pluginsBOOL 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 foundbWorking = 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 CDWordArraym_dwa.Add((DWORD)hm);}}
}

接下来,当你想要反复调用你的插件时,使用对每个插件存储的HMODULE来得到函数的地址,接着利用函数地址调用函数。

void CPluginDriverDlg::OnRunPlugins()
{for(int i=0; i<m_dwa.GetSize() ; i++){//Find a function and use itPFUNC 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的声明形式是:

typedef int (*PFUNC)(void);

最后,一定要确保做好清理工作,从内存中释放所有的DLL文件,方法是使用FreeLibrary()函数。我在测试代码的DestroyWindow()中完成了这个功能。

BOOL CPluginDriverDlg::DestroyWindow()
{for (int i=0; i<m_dwa.GetSize() ; i++){// Free all the libs we usedFreeLibrary((HMODULE)m_dwa[i]);}return CDialog::DestroyWindow();
}

实际上就是这么简单。你可以把任意多的插件放到预设的文件夹中;当你准备好后,执行插件中的函数。记住这是一个很简单的例子,它可以很简单地被扩充成健壮的模型,轻松载入你所需要的插件。

使用DLL作为插件的设计框架相关推荐

  1. android中的插件开发框架,设计并开发一个 Android 的插件化框架

    结合动态加载系列文章的分析,现在开始设计并开发一个 Android 的插件化框架,命名为 Frontia.Frontia 有 "前端" 的意思,寓意着 Android 插件能像前端 ...

  2. 插件式设计的架构模型与实例

    插件式设计近年来非常流行,其中eclipse起了推波助澜的作用,提到插件式就会不由自主的想到eclipse.其实插件式设计并不是什么新事物,早在几十年前就有了.像X Server就是基于插件式设计的, ...

  3. Winform开发框架之插件化应用框架实现

    支持插件化应用的开发框架能给程序带来无穷的生命力,也是目前很多系统.程序追求的重要方向之一,插件化的模块,在遵循一定的接口标准的基础上,可以实现快速集成,也就是所谓的热插拔操作,可以无限对已经开发好系 ...

  4. CAD插件-幕墙设计常用插件sama整理

    CAD插件-幕墙设计常用插件sama整理 SWF画弧形焊缝.LSP 标注多段线-(边长A1.对角线A2.角度A3)LSP 尺寸整理(修正)LSP 对齐afLSP 多段线顶点布块-(xxp)LSP 计算 ...

  5. 设计师不应该错过的响应式设计框架(含优缺点分析)

    Ethan Marcotte称响应式设计是基于网格建立一个网站.Marcotte定义这项技术后,响应式设计框架开始出现,主要是css和JavaScript的结合.许多框架都是开源的,可以免费下载和快速 ...

  6. SOA之(2)——SOA架构基础概念与设计框架

    SOA的设计框架 设计框架与架构相关的概念紧密相连,原则.模式和架构始终是与设计共舞的. SOA服务设计的原则中记录了一个基础的设计框架: 设计特性(Design Characteristic)--由 ...

  7. android插件化-apkplug框架基本结构-01

    2019独角兽企业重金招聘Python工程师标准>>> 由于框架开发更新频繁的原因一直都没有时间写出框架的基本架构让大家云里雾里的,现在框架已基本稳定和完善,我就抽出时间写写关于ap ...

  8. Origami – 用于 Quartz 的免费的交互设计框架

    Origami 是一个为 Quartz Composer 开发的免费的工具包--由Facebook设计团队创建,让交互设计原型更加简单,不需要编程. 如今,大多数设计师通过创建静态原型来表达要实现的应 ...

  9. Docker 的插件式设计

    http://www.tuicool.com/articles/MnIRZvJ http://uzhima.com/2016/08/02/what-is-docker-volume-plugin/ 在 ...

最新文章

  1. IBM HACMP 系列 -- 后期安装工作和管理任务二
  2. 程序员有趣的面试智力题(转)
  3. 子查询中的空值导致的问题。
  4. bat脚本注释多行_cmd批处理常用符号详解
  5. 计算机网络【在一个1Mb/s的卫星信道上发送1000bit长的帧。确认总是捎带在数据帧中。帧头很短,使用3位的序列号。对以下协议而言,可以取得的最大信道利用率是多少?(a)停-等协议;(b)(c)】
  6. 【传统PSTN与互联网通信】
  7. centos amd双显卡_PCIe4.0和PCIe3.0对显卡性能差别大吗?
  8. Leetcode分类
  9. EsayUI + MVC + ADO.NET(仓储基类)
  10. linux设置程序循环,linux shell编程学习笔记(7)流程控制之循环结构
  11. html中div的居中
  12. mysql sqlyog命令_SQLyog的基本使用
  13. 对视频播放url进行Blob加密
  14. Navicat Premium 12.0.29 / 12.1.5.0注册机激活
  15. 【5G核心网】 3GPP TS 系列解读
  16. esxi安装系统ndows,ESXI 安装 Windows Server 2012过程
  17. NOIP 模拟题 国际跳棋
  18. 图神经网络(ICML2022)
  19. iOS pch文件配置
  20. ICS课程学习(1)——概述

热门文章

  1. 微搭低代码入门教程-数据源介绍
  2. 诚心求问:做一个 Serverless SSR 需要几步?
  3. 深度学习论文精读01——基于多任务学习的肿瘤医学影像语义分割与分类研究
  4. 比较好的两个在线公式识别器
  5. 传智播客java博科学院怎么走_想去传智播客学习大家可不可以给的建议?
  6. SpringMVC——控制器方法的返回值类型(ModelAndView、String、void、Object)
  7. Linux系统应用:globbing通配及IO重定向
  8. java实现猜数字小游戏(1-100)
  9. 通过更改DllCharacteristics关闭ASLR地址空间随机化
  10. matlab latex换行,Latex 公式中换行问题