其实,插件不过就是调用dll中的函数而已,不过通过类似一个com中的接口,再通过接口查询到相应的服务来处理。
复杂的插件,当然有考虑采用com方式的,不过作为编写程序的原则是简单,实效,通用。又何须采用太过专业的方法。
技术不过是手段,能在达到目的的最大化程度上实现,就足矣。
下面的例子来自网上,作者不详,稍微整编下。直接贴代码在上面。源码打包放在自己博客的文档中。算是自己学习整理,
也感谢提供者。
源码学习:http://www.cppblog.com/Files/kenlistian/test_plus.rar
1.定义插件的接口结构
/*
定义一个plus 接口结构
*/
typedef struct PlugInModule{
DWORD Ver ; //版本
char *Author ; //作者说明
char *Description; //模块说明
BYTE *InputPointer; //输入数据
DWORD dwSize ; //输入数据的大小
HWND hParentWnd ; //主程序的父窗口
HINSTANCE hDllInst ; //Dll句柄
void (*PlugIn_Config)( struct PlugInModule * pModule ); //设置函数
void (*PlugIn_Init)( struct PlugInModule * pModule ); //初始化函数
void (*PlugIn_Quit)( struct PlugInModule * pModule ); //退出函数
void (*PlugIn_Run )( struct PlugInModule * pModule ); //执行函数
} PlugInModule;
其中接口结构函数,被规定了4个,也就是说这个接口函数定死了,如果以后应为功能增加等等,
则估计这个结构都要改写。所以采用com方式接口方式则是一种好的选择,而那种模式,每次还要注册com,
则莫免麻烦和钉死在windows平台上。
2.以上接口结构放置在头文件中。作为主程序和dll共享的头文件,其中,再在头文件中具体声明以上结构体中函数。
void plusDll_Config( struct PlugInModule * pModule); //设置函数
void PlusDll_Init( struct PlugInModule * pModule ); //初始化函数
void plusDll_Quit( struct PlugInModule * pModule ); //退出函数
void plusDll_Run( struct PlugInModule * pModule ); //执行函数
3.在头文件中声明一个返回该结构的函数。其实就是一个回调函数。把该结构返回给主程序的一个export 函数。
typedef PlugInModule* (*GETPLUGINMODULE)(); //声明接口函数地址
/**
导出函数,主程序首先获取该接口函数,获得 dll中的函数地址,调用
*/
DLL_001_API PlugInModule* GetPlugInModuleFunction(); //DLL_001_API ==> __declspec(dllexport)
4.在dll中定义该插件结构,把地址通过GetPlugInModuleFunction传入到主程序。
5.分别实现dll中和主程序的定义部分。通过动态加载方式即可实现取出dll的结构体指针。
如下示:
hDLL = LoadLibrary("dll_001\\debug\\dll_001.dll");
if (hDLL)
MessageBox(NULL,"plus_Dll load ok", "", MB_OK);
else
{
MessageBox(NULL, "not found plus_dll","",MB_OK);
return 0;
}
pFunction = (GETPLUGINMODULE)::GetProcAddress(hDLL,"GetPlugInModuleFunction");
if (pFunction != NULL)
{
dllplus_module = (*pFunction)();
dllplus_module->PlugIn_Init(dllplus_module);
dllplus_module->PlugIn_Run(dllplus_module);
dllplus_module->PlugIn_Quit(dllplus_module);
}
::FreeLibrary(hDLL);//卸载MyDll.dll文件;