插件化软件设计的问题
前两天看到一篇帖子讨论关于插件化软件设计的
如何做“插件化软件”,“模块化软件”设计。
正好手边也需要类似的功能,看完后挺有启发。
针对我目前的需求,还有一些问题没有解决,需要向大家请教的。
软件的功能如下:
1. 是一个硬件采集程序。
2. 主程序主要负责界面绘制和加载各功能DLL。
3. 其中有一个DLL主要负责采集设备的初始化,生成一个设备对象。
4. 其它有多个DLL用于针对采集的数据做处理,每个DLL一个处理功能,可以循环调用每个DLL的功能做处理,处理结果加到一个队列中。
主要有以下问题:
1. 以前只做过简单的DLL调用,基本调一个函数就完了。这次需要在多个DLL中共享数据,还有类对象实例,看了些文章介绍,其中提到类对象的话在DLL间共享的话可能会有问题,微软MSDN就不推荐共享C++类 http://msdn.microsoft.com/zh-cn/library/h90dkhs0(v=vs.80).aspx
2. 一个DLL负责设备初始化,设备对象是以C++类形式定义的,同样也是第一个问题;设备有多种不同设备,为了适应不同设备需要和以后添加设备,这个共享的对象应该怎么定义才能为以后的升级和复用带来方便(不影响使用该对象的DLL)。
3. 上面4中的方法,首先由初始化DLL初始化设备,然后循环控制是否应该交给主程序,那样的话在主程序中还是要调用设备对象的方法,不知该如何实现。
[最优解释]
之前有实现过类似的设计:
#ifndef PLUGIN_API
#define PLUGIN_API __declspec(dllexport)
#endif
extern "C" PLUGIN_API void RegisterPlugin(VPFactory& factory){
process... results;
factory.push_back(results);
}
extern "C" PLUGIN_API void UnReisterPlugin(VPFactory& factory){
factory.erase(results);
}
// 遍历指定文件夹下的dll插件。
void MainWindow::setupFactory()
{
//get the program's directory
wchar_t dir [MAX_PATH];
::GetModuleFileName (NULL, dir, MAX_PATH);
//eliminate the file name (to get just the directory)
wchar_t* p = ::wcsrchr (dir, '\\');
*(p + 1) = 0;
//find all DLLs in the plugins subdirectory
wchar_t search_parms [MAX_PATH];
::wcscpy_s (search_parms, MAX_PATH, dir);
::wcscat_s (search_parms, MAX_PATH, L"plugins\\*.dll");
WIN32_FIND_DATA find_data;
HANDLE h_find = ::FindFirstFile (search_parms, &find_data);
BOOL f_ok = TRUE;
while (h_find != INVALID_HANDLE_VALUE && f_ok)
{
//load each DLL and determine whether it is exporting the functions we care about
wchar_t plugin_full_name [MAX_PATH];
::wcscpy_s (plugin_full_name, MAX_PATH, dir);
::wcscat_s (plugin_full_name, MAX_PATH, L"plugins\");
::wcscat_s (plugin_full_name, MAX_PATH, find_data.cFileName);
HMODULE h_mod = ::LoadLibrary(plugin_full_name);
if (h_mod != NULL)
{
// 保存插件列表
loadedPlugins.push_back(h_mod);
// 注册插件
PLUGIN_FUNC_PTR p_register_function =
(PLUGIN_FUNC_PTR) ::GetProcAddress (h_mod, "RegisterPlugin");
if (p_register_function != NULL)
{
// 将结果放到factory单件实例中。
(*p_register_function)( VPFactorySingleton::Instance() );
}
}
//go for the next DLL
f_ok = ::FindNextFile (h_find, &find_data);
}
}