摘 要:本文介紹了一種通過基于動態鏈接庫的插件技術實現監控程序的在線功能擴展的方法。通過西門子的PRODAVE軟件和VC++實現了對S7-300PLC的監控,從而檢驗了方案的可行性。
關鍵詞:動態鏈接庫、插件、PRODAVE、VC++
1概述
在過程控制系統中,上位監控程序已經成了系統不可缺少的組成部分。通過上位監控程序對系統進行控制可以使操作的難度和復雜度都大大降低。隨著計算機功能的日益增強,監控程序能完成的功能也越來越多,在有些情況下可以讓上位機協助下位機完成控制功能。
目前,上位機程序設計主要有兩種方式,其一是采用專門的組態軟件,如WinCC、組態王等;另外就是通過編程語言自行開發。第一種方法操作簡單、效率高、對開發人員的要求相對較低,但成本較高;第二種方法相對要復雜,要求開發者具有較高的編程水平,開發周期長,但與第一種方法比具有靈活、成本低的優點。對于規模較小的項目出于降低成本的考慮可以采用第二種方法進行開發。采用第二種方法就需要解決一些額外的技術難點,比如系統已經投入運行后可能會由于生產規模的擴大等原因需要增加額外的設備或模塊,這種情況下就要求監控程序也要做出相應的改動。這時采用第二種方法開發的程序一般就會遇到修改工作量大、需要停機升級程序的問題。特別對于后一問題,在上位機協助下位機完成控制功能時是應該盡量避免出現的。本文就是針對這一問題提出的基于插件技術的解決方案。
2插件背景知 識
2.1插件原理
插件是一種遵循一定規范的應用程序接口的程序,可以理解為一個插件就是一種新功能。實現插件功能對插件容器和插件本身都要進行考慮。這里首先要解決的問題就是插件容器不知道將來要安裝的插件要實現什么功能,而插件本身可能需要知道一些插件容器的信息來更好的實現與容器之間的結合。基于這種考慮,就需要在它們之間定義具體的接口(一般采用接口函數),接口的實際功能完全依賴于插件本身,如圖1所示。
[align=center]

圖1 插件結構圖[/align]
采用插件的主要目的就是在不改動監控程序(插件容器)的前提下擴展監控程序的功能,因此,應該在程序設計之初就要考慮接口函數的參數和返回類型。另外,由于插件一般是在程序運行過程中安裝的,那么在下一次程序啟動的時候希望程序能自動的添加已經安裝過的插件,因此要使監控程序對已經安裝的插件進行統一管理。
2.2動態鏈接庫(DLL)
DLL是建立在客戶/服務器通信的概念上,包含若干函數、類或資源的庫文件。函數和數據被存儲在一個DLL(服務器)上并由一個或多個客戶導出而使用,這些客戶可以是應用程序或者是其它的DLL。
微軟的Visual C++支持三種DLL,它們分別是Non-MFC DLL(非MFC動態庫)、Regular DLL(常規DLL)、Extension DLL(擴展DLL)。Non-MFC DLL指的是不用MFC(微軟基礎類)的類庫結構,直接用C語言寫的DLL,其導出的函數是標準的C接口,能被非MFC或MFC編寫的應用程序所調用。Regular DLL和下述的Extension DLL一樣,是用MFC類庫編寫的,它的一個明顯的特點是在源文件里有一個繼承CWinApp的類(注意:此類DLL雖然從CWinApp派生,但沒有消息循環,被導出的函數是C函數、C++類或者C++成員函數),調用常規DLL的應用程序不必是MFC應用程序,只要是能調用類C函數的應用程序就可以,它們可以是在Visual C++、Dephi、Visual Basic、Borland C等編譯環境下利用DLL開發的應用程序。
常規DLL又可細分成靜態鏈接到MFC和動態鏈接到MFC上的。與常規DLL相比,使用擴展DLL用于導出增強MFC基礎類的函數或子類,用這種類型的動態鏈接庫,可以用來輸出一個從MFC所繼承下來的類。
擴展DLL是使用MFC的動態鏈接版本所創建的,并且它只被用MFC類庫所編寫的應用程序所調用。擴展DLL 和常規DLL不一樣,它沒有一個從CWinApp繼承而來的類的對象,所以,開發人員必須在DLL中的DllMain函數添加初始化代碼和結束代碼。
2.3插件DLL特性
插件DLL的最大特點就是它具有固定的結構。作為容器的監控程序一旦發布,插件的結構也就不能再改變了。因此良好的插件結構設計對將來的功能擴展來說至關重要。
為了提高開發效率,選用支持MFC的DLL是一個不錯的選擇。需要注意的是如果要從DLL導出繼承自MFC的類的對象最好使用擴展DLL,否則可能導致DLL中的對象和導出的對象存在差異。
3示例編程
以下示例簡單的實現了對監控畫面的擴展。監控主程序只對一個PLC進行監控,通過后續的插件可以在不影響主程序的前提下實現對更多PLC的監控(這里只擴展了一臺)。
3.1 插件部分
在VC 6.0的AppWizard中選擇”MFC AppWizard(dll)”,并在下一步選擇” MFC Extension DLL”(因為在此例中要導出繼承自MFC的類的對象)。在資源中插入一對話框模板,設置屬性為”Child”、”Thin”、”Title bar”,并為它創建一個以CPropertyPage為基類的新類CPage。接下來要做的就是進行數據采集和監控界面的設計。PRODAVE是用于PC與S7系列PLC之間的數據鏈接通信的工具箱。通過PC的MPI通信處理器,例如CP5511、CP5611,或PC/MPI適配器(PC-Adaptor),可以方便地在PLC與PC間建立數據鏈接[3]。值得注意的是,由于使用了MFC擴展DLL,所以必須動態加載PRODAVE的DLL文件。方法如下:
① 定義函數指針
typedef int (WINAPI *Ploadtool)(char,char *,adr_table_type *);
② 加載DLL并獲得函數指針
hProdave=LoadLibrary("W95_s7.dll");
Ploadtool loadtool=(Ploadtool)GetProcAddress(hProdave,"load_tool");
Punloadtool unloadtool=(Punloadtool)GetProcAddress(hProdave,"unload_tool");
③ 調用函數
loadtool(1, "S7ONLINE", &adr_table);
完成插件的具體功能后還需要實現導出函數:
void showprop(void**dlg)
{ *dlg=new CPdlg;
}
3.2 監控程序
因為插件DLL導出的是一個屬性頁,所以可以在監控程序中添加此屬性頁。結合前文所述,監控程序所要實現的功能主要有主體監控功能、加載插件DLL、啟動時自動加載插件。
① 主體監控功能
這里實現了監控程序的大部分功能,如主監控畫面的設計等,但此處不是本文所要論述的重點。
② 加載插件DLL
此功能在函數BOOL CTestdllDlg::CreateObjectFromPath CreatePlugPage(CString name)中實現:
BOOL CTestdllDlg::CreatePlugPage(CString name)
{BOOL brt=FALSE;
PAGE temp;
if(name){
temp.hdll=LoadLibrary(name);
if(temp.hdll)
{ fun func=(fun)GetProcAddress(temp.hdll,"showprop");
if(func)
{ func((void**)&temp.page);
s.AddPage(temp.page);
brt= -1!=pagelist.Add(temp);
}
}
}
if(!brt)
FreeLibrary(temp.hdll);
return brt;
}
創建目錄并保存DLL文件:
CreateDirectory(m_strPlugFile, NULL); // m_strPlugFile為指定目錄名
if (!CopyFile(filename, m_strPlugFile, TRUE)) // filename為插件DLL文件名
{ return;
}
③ 啟動時自動加載插件
此功能在函數BOOL CTestdllDlg::CreateObjectFromPath(LPCTSTR szPath)中實現:
BOOL CTestdllDlg::CreateObjectFromPath(LPCTSTR szPath)
{ CString strPath = szPath;
CString strFindFile = szPath;
strFindFile += "\\*.dll";
WIN32_FIND_DATA wfd;
HANDLE hf = FindFirstFile(strFindFile, &wfd);
if (INVALID_HANDLE_VALUE != hf){
CreatePlugPage(strPath + "\\" + wfd.cFileName);
while (FindNextFile(hf, &wfd)){
CreatePlugPage(strPath + "\\" + wfd.cFileName);
}
FindClose(hf);
}
return TRUE;
}
4總結
很多文獻資料都曾介紹過監控軟件的開發[4],但卻很少涉及成熟的開發軟件所具有的在線修改功能,這就限制了監控軟件的應用范圍。本文中提出的方法正是對這一不足進行的必要補充。示例程序成功實現了在主監控程序的基礎上通過插件的方法實現對更多PLC的監控,說明了監控程序是如何應對生產設備增加這一情況的。采用這種方法不僅能成功解決自主開發的監控程序需要停機進行功能擴展的問題,而且不需要對主監控程序進行任何改動,從而大大降低了工作量。
參考文獻:
[1] 王艷. 用VC制作動態連接庫. 北京:微計算機信息. 2003.5: 70~71.
[2] 廖常初. S7-300/400 PLC應用技術. 北京: 機械工業出版社.2005.
[3] 姜建芳、蘇少鈺等.西門子S7-300系列PLC與PC機通信實現的研究.制造業自動化.2003.1:52~54.
[4] 王亞民、陳青等.組態軟件設計與開發.西安:西安電子科技大學出版社.2003.
[5] MSDN Library online. Microsoft corporation.