創建最簡單的exe形式COM組件並在MFC程式調用
- 2019 年 10 月 3 日
- 筆記
來新公司學習接手新項目,拿到程式碼打開解決方案看到裡面竟然有40幾個工程,有點吃驚。具體看程式碼也有很多之前沒見過的寫法,上了幾天火。
有件事就沒太搞明白,按照文檔的說法上層很多軟體都要調用IO伺服器,但看程式安裝目錄,IO伺服器其實是一個exe程式,按照我之前的印象,能被別的程式調用的也得是動態庫、靜態庫或者服務。實在想不通exe程式怎麼作為介面被別的程式調用的。
結果昨天研究了一天,想通了,這個IO伺服器其實就是COM組件。
按照網上的說法: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組件支援分散式使用。