<menu id="w8yyk"><menu id="w8yyk"></menu></menu>
  • <dd id="w8yyk"><nav id="w8yyk"></nav></dd>
    <menu id="w8yyk"></menu>
    <menu id="w8yyk"><code id="w8yyk"></code></menu>
    <menu id="w8yyk"></menu>
    <xmp id="w8yyk">
    <xmp id="w8yyk"><nav id="w8yyk"></nav>
  • 網站首頁 > 物聯資訊 > 技術分享

    一種松耦合的分層插件系統的設計和實現

    2016-09-28 00:00:00 廣州睿豐德信息科技有限公司 閱讀
    睿豐德科技 專注RFID識別技術和條碼識別技術與管理軟件的集成項目。質量追溯系統、MES系統、金蝶與條碼系統對接、用友與條碼系統對接

    C++編寫的桌面軟件中傳統的App+Dll的架構已經顯現出的模塊之間的強耦合、維護性差、升級不方便等諸多弊端,為此我進行了一些思考,有興趣的朋友請看我以前的一個思考片斷:《Windows平臺下C++插件系統實現的幾個關鍵技術問題及其解決思路》,今天則具體介紹的我的一個具體設計和實現。

     

            我的目標是要去除功能模塊的相互依賴,在模塊調用必須采用動態加載的辦法,但同時各個模塊可以進行自由地進行通訊。我的設想大致是這樣的:在動態加載各個模塊后調用統一接口后生成插件對象,在某個插件對象都能通過標識符找到其它的插件對象,通過統一的接口將數據傳給它們。系統架構圖如下:

    RFID設備管理軟件

    RFID設備管理軟件

    系統流程圖如下:

     RFID設備管理軟件

               大家可以看到,要構建這樣的系統需要解決兩個關鍵問題:

     

    1. 如何動態加載dll創建插件對象以及插件基類對象的接口設計

     

    2. 插件模塊之間的通訊問題

     

             如何解決這兩個問題我已有了基本的思路。為了驗證我的思路是可行的,我用VC2008新建了一個LayeredArchit解決方案,該解決方案實現這樣一個簡單功能:統計指定目錄下的文件數,然后將統計結果保存到一個文本文件。這個解決方案由以下工程組成:

     

    BaseObjLib   ——   底層庫,用于定義底層對象和接口

     

    StatFile    ——  統計文件插件

     

    OutputFile ——  將統計結果輸出到文本文件的插件

     

     CmdApp   ——  一個主調用程序(是一個控制臺程序)。

     

     

             在每個插件模塊都實現一個插件對象,繼承基類插件對象IPluginObj,里都有這樣一個統一的插件導出接口來生成插件對象:

    [cpp] view plaincopy
    1. extern "C" __declspecdllexport )  IPluginObj* __stdcall GetPluginObj(const std::string &strID)  

                在動態加載插件庫之后就調用這個接口。這樣就解決了動態創建插件對象的問題。


               接下來我們解決插件之間的數據通訊問題。前面的設計已經實現了在任何插件模塊里都能找到其它的插件對象。一個很自然的設計是在基類定義這樣一個接口:

    [cpp] view plaincopy
    1. virtual BOOL ProcessData(void* pData){ return FALSE;}  

     

          然后在派生插件對象里重載這個接口。這個設計基本可以實現數據通訊,但是有一個嚴重弊端是void*是類型不安全的,假如數據接收方將其類型轉換錯了程序就很可能崩潰。特別是當一個插件需要接受兩種類型數據時。因此必須解決類型安全問題。


            之后我想到了利用微軟的com模型的萬能類型VARIANT,但是看了一篇文章《用戶自定義結構數據與VARIANT轉換》就放棄了,感覺轉換太繁瑣了。后面驚喜地發現原來boost庫早已實現了一個萬能類型boost::any。boost::any真的很符合我的需求。具體是在基類插件對象類定義一個虛接口:


    [cpp] view plaincopy
    1. virtual BOOL ProcessData(boost::any& anyData){ return FALSE;}  

           在主程序里找到統計插件對象,并將路徑傳遞給它:

    [cpp] view plaincopy
    1. IPluginObjPtr ptrStatFile = pPluginFactory->GetPlugin(_T("StatFile.dll"));  
    2. std::string strFolder = _T("D:\\dev-utility-tools\\doc");  
    3. boost::any anyString = strFolder;  
    4. ptrStatFile->ProcessData(anyString);  

    // 統計模塊的ProcessData函數的實現

    [cpp] view plaincopy
    1. BOOL CStatFilePlugin::ProcessData( boost::any& anyData )  
    2. {  
    3.     if(anyData.type() == typeid(std::string))    
    4.     {  
    5.         std::string strPath  = boost::any_cast<std::string>(anyData);   
    6.         if(::GetFileAttributes(strPath.c_str())==-1)  
    7.         {  
    8.             std::cout<<"目錄不存在"<<std::endl;  
    9.             return FALSE;  
    10.         }  
    11.         m_info.m_strPath = strPath;  
    12.         std::cout<<"現在正在統計的是:"<<m_info.m_strPath<<std::endl;  
    13.         std::cout<<"請等待!!!"<<std::endl;  
    14.           
    15.         std::string strTmpDir = m_info.m_strPath + TEXT("\\");  
    16.         // 統計文件數  
    17.         StatAllFileInFolder(strTmpDir);  
    18.   
    19.         std::cout<<"文件夾數:"<<m_info.m_FolderNum<<std::endl;  
    20.         std::cout<<"文件數:"<<m_info.m_FileNum<<std::endl;  
    21.   
    22. // 找到輸出到文件插件對象,將統計結果傳給它  
    23.         CPluginFactory* pPluginFactory = CPluginFactory::Instance();  
    24.         IPluginObjPtr ptrOuttoFile = pPluginFactory->GetPlugin(_T("OutputFile.dll"));  
    25.         boost::any anyInfo = m_info;  
    26.         ptrOuttoFile->ProcessData(anyInfo);  
    27.   
    28.         return TRUE;  
    29.     }  
    30.     return FALSE;  
    31. }  

            這樣就安全地實現了插件間的數據通訊。需要指出的是需要通訊的插件間不相互依賴,但需要都包含的定義了傳遞數據結構體的頭文件。具體請見源碼下的DataExchange文件夾,該文件夾就是定義需要通訊的數據結構體。


    程序的效果圖如下:

    RFID設備管理軟件

             一個擴展設想是:消息本質上也是一種數據。消息的傳遞也可以參考數據的傳遞來實現。

     

            源碼已上傳至http://code.google.com/p/dev-utility-tools/source(具體見PluginArchit解決方案),采用GPL V2.0開源協議,有興趣請下載看看。

     

    參考文獻:

     

    1.     4.6.1 萬能類型boost::any

     

     

    from:http://blog.csdn.net/clever101/article/details/8656720

    RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成
    最近免费观看高清韩国日本大全