來新公司學習接手新項目,拿到代碼打開解決方案看到裏面居然有40幾個工程,有點吃驚。具體看代碼也有不少以前沒見過的寫法,上了幾天火。git
有件事就沒太搞明白,按照文檔的說法上層不少軟件都要調用IO服務器,但看程序安裝目錄,IO服務器實際上是一個exe程序,按照我以前的印象,能被別的程序調用的也得是動態庫、靜態庫或者服務。實在想不通exe程序怎麼做爲接口被別的程序調用的。程序員
結果昨天研究了一天,想通了,這個IO服務器其實就是COM組件。github
按照網上的說法:COM component(COM組件)是微軟公司爲了計算機工業的軟件生產更加符合人類的行爲方式開發的一種新的軟件開發技術。在COM構架下,人們能夠開發出各類各樣的功能專注的組件,而後將它們按照須要組合起來,構成複雜的應用系統。由此帶來的好處是多方面的:能夠將系統中的組件用新的替換掉,以便隨時進行系統的升級和定製;能夠在多個應用系統中重複利用同一個組件;能夠方便的將應用系統擴展到網絡環境下;COM與語言,平臺無關的特性使全部的程序員都可充分發揮本身的才智與專長編寫組件模塊。小程序
COM組件能夠是dll或者exe或者服務的形式。服務器
按照這個思路,代碼就看懂了很多,之因此解決方案裏有那麼多工程,也不過是由於劃分了不少動態庫和COM組件。網絡
又花了些時間,寫了個小程序來實現最簡單的exe形式COM組件的生成與調用,以下:分佈式
首先創建一個ALT工程:函數
在類視圖裏,爲工程添加ALT的類,和接口:學習
這裏定義了類,和對應的接口(Interface),注意ProgID要寫,待會程序調用com接口時,要經過ProgID找com組件字體
以後項目目錄以下,在.idl文件裏有com接口(interface),裏面還定義了com組件的id等等不贅述了,實現類在ATLTest.cpp裏,其對應關係都是vs自動搭建的。
接下來仍是在類視圖裏具體添加方法(接口和實現):
方法內部寫程序,邏輯是兩數求和:
STDMETHODIMP CCATLTest::ATLTestFunc0(SHORT num1, SHORT num2, SCODE* pRetNum) { *pRetNum = num1 + num2; return S_OK; }
而後編譯會出錯,那是由於執行com組件註冊命令時候,缺少管理員權限,
從新啓動vs,以管理員權限運行便可。
接下來建一個mfc項目,這不是今天主題就不贅述了,
在界面上簡單填個按鈕和輸入框,寫個兩數求和的圖形界面demo,
具體的求和的方法要調用com組件。
mfc項目裏添加com接口,在類嚮導裏選擇添加類,選atl,選TypeLib中的MFC類:
以後能夠選取前面定義的Lib:
加入COM接口文件後,就能夠調用了,注意我下面的寫法:
void CATLMfcClientDlg::OnBnClickedGetRetButton() { CoInitialize(NULL); CATLTest myCom; if (!myCom.CreateDispatch(_T("ATLTest.math.1"))) { MessageBox(L"組件註冊失敗"); return; } CString strNum1,strNum2; // 獲取用戶輸入的數字 this->numInput1.GetWindowTextW(strNum1); this->numInput2.GetWindowTextW(strNum2); // 調用COM接口,兩數求和 short ret = myCom.ATLTestFunc0(_wtoi(strNum1),_wtoi(strNum2)); WCHAR buf[50]; _itow(ret,buf,10); // 顯示結果 this->numRet.SetWindowTextW(buf); CoUninitialize(); return; }
運行效果:
上面有說的簡略的地方,具體能夠看我上傳git的源碼:
https://github.com/SonnAdolf/MyAtlExeComDemo
額外內容:
動態連接庫和COM組件的區別
1動態連接庫的表現形式只能是dll[變態該名的除外], COM組件的表現形式能夠是dll也能夠是exe。
注:其實字體、驅動等也算是動態連接庫的一種,這裏略去...
2 動態連接庫的生成和編譯器及系統相關,在Windows/Linux下系統,須要分別編譯才能使用。
COM組件是二進制編碼,在Windows和Linux下能夠直接使用,不須要從新編譯。
3 COM組件是按照COM規範實現的dll或者exe;動態連接庫是一個能夠導出函數的函數集合。
4 動態連接庫只能在本機被調用,COM組件支持分佈式使用。