建立最簡單的exe形式COM元件並在MFC程式呼叫
來新公司學習接手新專案,拿到程式碼開啟解決方案看到裡面竟然有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/MyAtlExeCom