|
|
運動控制卡發(fā)展越來越訊速,不同類型的控制卡亦多種多樣,使軟件項目經(jīng)理具備越來越靈活的方案選擇。而對于軟件開人員,對不同的類型卡的性能測試工作無疑也越來越麻煩,通常各類型的控制卡其驅動庫函數(shù)各不一樣,都需要用戶自己進行整理封裝。本文的目的就是通過C++方式編程,探討一下實現(xiàn)多類型卡編程方式,以供開發(fā)人員參考。
一、利用C++虛擬函數(shù)機制 除了手動去單個修改替換以前卡的驅動函數(shù)之外,此方法最易被C++程序員所想起,其方法是,首先需要建立一個通用的基類(父),然后不同卡封裝的類通過重寫基類的虛擬函數(shù)來實現(xiàn),代碼看上去大致如下: class CDviece//用戶根據(jù)自己的設置建立的基類 { public: virtual int InitBoard(); //在此僅以初始化函數(shù)為例 … (略) };
class CDmc1000Card: public CDviece // 設該卡為雷賽的DMC1000卡 { public: virtual int InitBoard() { return dmc1000_init_board(); }//改進基類的InitBoard函數(shù) …(其它改寫略去) }
class COMS: public CDviece //設該卡為美國的OMS卡 { public: virtual int InitBoard() {
} …(其它改寫略去) }
在程序中,若想設備使用DMC1000控制卡,可定義如下: CDviece *pMineDviece = new CDmc1000Card; 改為OMS控制卡則一樣: CDviece *pMineDviece = new COMS; 而其它代碼調用InitBoard函數(shù)可以不去改動,照常使用: if( pMineDviece->InitBoard() ) { …(Do s.th) }
使用此方法,需要根據(jù)當前設備配置情況,完整的寫好CDviece的所有函數(shù),同樣,從CDviece派生的控制卡類,也需要將父類虛擬函數(shù)全部改寫完畢,對函數(shù)返回值,參數(shù)都需要進行規(guī)范,同時,修改完成之后,將整個軟件工程全部編譯一次。 利用虛擬函數(shù)方法,會帶來虛擬函數(shù)表的成本開銷,隨著CDivece需要的函數(shù)增加,其成本會相應的增加,事實上,MFC的消息機制就是以代碼的方法實現(xiàn)了虛擬函數(shù)的機制,只不過虛擬函數(shù)的處理是通過C++編譯器來完成的。 并且,CDviece的需求發(fā)生變化時,其派生類的函數(shù)相應的也要發(fā)生變化,這一點是程序員需要注意的。
二、利用DLL動態(tài)庫實現(xiàn) 從COM組件編程過來的人,很容易想到DLL的實現(xiàn)方案?粗剡@一點是的只要主程序框架寫得正確,改變DLL即可實現(xiàn)主程序不編譯,即可獲得不同類型卡的選擇。 事實上,這是一種美好的愿望,要實現(xiàn)起來并不容易,而且很需要程序員有熬夜的精神。大致偽代碼實現(xiàn)如下:
class CDviece { private: HANDLE dllHandle; public: typedef int( *P_InitBoard)(void ); P_InitBoard InitBoard; …(其它所有定義及聲明略去)
int InitFunction( char *dllFileName )//調用DLL文件 { dllHandle = LoadLibaray( dllFileName ); InitBoard = (P_InitBoard)FindFunction(dllHandle, “Init_Board”); … (其它略去) } } 由于不同卡的函數(shù)名都不一樣,故需要程序員按照CDviece所需函數(shù)進行另一DLL的編寫,若需要DMC1000控制卡時,則需要生成一個MDMC1000.dll如下:
int InitBoard() { return dmc1000_board_init(); } …(其它略去)
生成OMS控制卡的MOMS.dll如法炮制: int InitBoard() { } …(其它略去)
在代碼中調用DMC1000控制卡,使用如下: CDviece mineDviece; mineDviece.LoadLibaray(“Mdmc1000.dll”); if( mineDviece.InitBoard() ) { …(Do s.th) } 使用OMS控制卡如下: mineDviece.LoadLibaray(“Moms.dll”); …(其它略去)
看似簡單,實質上略去的部分將是程序員的一場惡夢,想一想那一大堆的定義和聲明,一碰到CDviece的變動,哪怕是最小的函數(shù)返回值或參數(shù)變動,則其它相應的所有DLL都需跟全部編譯。這無疑給軟件項目的整個維護帶來極大的難度。
三、利用模板類實現(xiàn) 探討到現(xiàn)在,本人比較推薦的就是使用此方法,它較虛擬函數(shù)相比無額外成本的開銷,更不有因為虛擬函數(shù)帶來的效率問題。 與DLL方法相比,定義聲明,及變動性都非常良好,整個維護的成本也較低。 其編程特點即是,通過模板定義一個空殼類,然后根據(jù)需要可以邦定不同類型的控制卡。其偽代碼實現(xiàn)方法如下:
//定義一個空殼類 template class CDviece: public CARD { public: CDviece(){} ~CDviece(){} }//簡單吧,了無秘密可言
以下定義DMC1000封裝類: class CDmc1000Card //無需繼承 { public: int InitBoard( void ) { return dmc1000_board_init(); } …(其它略去) }
以下定義OMS封裝類: class COMS { public: int InitBoard( void ) { } }
在程序中應用時,調用DMC1000控制卡如下:
typedef CDviece DEVIECE; DEVIECE mineDviece; if( mineDviece.InitBoard() ) { …(Do s.th) } 當然,DEVIECE的定義也可以如下形式: class DEVIECE: public CDviece { public: DEVIECE(){} ~DEVIECE(){} } 調用OMS控制卡如下: typedef CDvieceDEVIECE; …(其它同上)
可以看到,此方法還是讓人感到興奮的。即使參數(shù)或聲明發(fā)生變化或忘記定義,那就讓編譯器來查錯吧! 順帶提一下,由于控制卡封裝時,總有一些數(shù)據(jù)結構是通用的,對此解決方法也很簡單,實現(xiàn)如下: struct tag_CARD { …(定義通用數(shù)據(jù),如每轉脈沖數(shù),最大速度值,行程范圍等等之類) } 再改變一下CDmc1000Card如下形式: class CDmc1000Card: public tag_CARD //其它不變,OMS的定義同理
四、設立一個卡類型變量 此方法最為簡單,缺點是需要同時鏈接全部的控制卡驅動庫函數(shù),且在程序安裝時,還需要考慮各種控制卡的驅動程序或其相應的動態(tài)庫是否存在。其偽代碼形式下如: enum{ NOCARD=0,DMC1000=1, OMS=2 …}; class CCtrlCard { public: int m_nCardType;//記錄控制卡類型變量
CCtrlCard():NOCARD(0){} ~CCtrlCard(){}
int InitBoard( int nCardType ) { m_nCardType = nCardType; switch( nCardType ){ case DMC1000: if( d1000_board_init() <= 0 ) m_nCardType = NOCARD;//初始化失敗 else{ } break; case OMS: … break; default: m_nCardType = NOCARD; } return m_nCardType; } //其它省略 };
調用時偽代碼形式如下: CCtrlCard card; if( card.InitBoard( DMC1000 ) != DMC1000 ) //初始化失敗 else //找到控制卡
|
|
狀 態(tài):
離線
公司簡介
產(chǎn)品目錄
|
|
公司名稱:
|
深圳市雷賽智能控制股份有限公司
|
聯(lián) 系 人: |
梁邦敏
|
電 話: |
755-26401178
|
傳 真: |
|
地 址: |
深圳市南山區(qū)登良路天安南油工業(yè)區(qū)2棟3樓 |
郵 編: |
518000 |
主 頁: |
|
|
|
|
|