關於C++編寫com和調用com組件的小例子以及個人所犯錯誤見解

最近在完成研究生課程面向對象方法的第一次作業編寫一個com:

環境Visual Studio 2015

一、構造COM組件,項目名稱爲ComZhh,過程

進入VS,選擇左上角的文件,點擊新建項目->Visual C++->ATL->ATL項目

注意在下一步中勾選支持com+1.0

接着你講看到項目下有兩個目錄

不要着急,你只需要關注ATLProject1即可。然後,你需要開始定義組件內部的類,也就是你的組件的功能部分,我只講解定義一個功能的內容。在你的項目下,右鍵添加->添加類->ATL->ATL簡單對象

在此後注意下圖中的ProgID這一欄,填寫完類名之後你需要給你的組件一個名稱,它是唯一的,在C++d額客戶程序中查找你所定義的類的時候至關重要,

我定義的名稱爲hello.important,要着重強調。然後點擊完成即可,然後注意要找到你的解決方案資源管理器中的類視圖!注意 是類視圖。

在類視圖中可以看到剛剛定義的hello類,但是名稱和我們實際定義的不太一樣,變成了Chello和Ihello,不過不用擔心,你不需要在意,你只需要在Ihello也就是你的類的接口類上右鍵,->添加->添加方法,定義你所需要的函數

我們可以看到out、retval那兩個地方是灰色的,並且在我所看到的教程中大多數人沒有提到如何使用,因爲out模塊代表的是函數的返回值,如果不定義out特性的參數,則無法獲得調用函數所獲得的返回值。因此我們需要定義一個指針類型的參數,

當你選擇了指針類型的參數類型後,out和retval會自動變成可選的,此時在out上打勾,表明zheli這個參數是用來獲取返回值的。

也就是現在這個樣子,此時你可以看到你的類和接口類中同時都存在了hahaha函數的定義

此後開始實現你的方法

Chello就是你所定義的hello,只是說在頭文件中系統自動定義成了Chello類而已 ,並不影響理解和使用。return S_OK是com組件中任意函數的返回值,【out】特性纔是返回值,這也可以保證一個函數可以有多個輸出值

此時com組件就定義完成了,點擊生成->生成解決方案

此時可以在代碼的項目目錄中看到dll 文件,使用管理員運行cmd,進入dll所在目錄執行

regsvr32   “ATLProject1.dll” 將dll添加到註冊表中即可。

下面介紹如何通過C++調用com組件

首先新建一個win32的控制檯應用程序

直接點擊完成即可,然後複製你要調用的dll文件到vs的目錄下面,因爲如果不這麼做vs中c++的import會提示無法打開源文件(.tlh)如下:

然後進入ConsoleApplication1.cpp構建調用函數

此時會顯示C1083的錯誤,注意在這裏我犯了錯誤,因爲dll添加進項目的步驟應該是先將dll複製到項目文件夾下然後再vs中的項目中點擊添加->添加現有項,選擇你將要使用的dll文件,點擊添加。

當你這麼執行了添加操作之後,仍然會提示無法打開.tlh文件,這可能是vs的小bug?不要着急,接下來直接點擊 生成->清理解決方案 然後點擊 生成->重新生成解決方案,你會發現此時錯誤以及程序中import下的紅線神奇的消失了,此時import就已經成功了,你可以開始盡情調用了。噢 對 應該是#import"ComZhh.dll" no_namespace ,後面的no_namespace應該也挺重要的,雖然還不是太懂,畢竟剛剛接觸QAQ。

 

int main()
{
	
	CoInitialize(NULL);
	 CLSID clsid;
	 CLSIDFromProgID(OLESTR("hello.important"), &clsid);//!!!!!這個是你創建ATL的時候定義的 
     //progid!不要被網上的“dll名稱+接口”誤導!!!這個地方只要寫錯不管怎麼調試都無法調用dll
	CComPtr<Ihello> pHello;//智能指針
	pHello.CoCreateInstance(clsid);
	Long* result;
	pHello->hahaha(&result);

	pHello.Release();//小心哦!!請看最後的“注意”
	CoUninitialize();


    return 0;
}

填寫完成代碼之後直接調試就ok啦

如果是bstr*的result有如下的操作需要注意:

        BSTR result;
	pShoot->showShoot(&result);	
	char* resultConvert=_com_util::ConvertBSTRToString(result);
	std::cout << resultConvert;
	SysFreeString(result); // 用完釋放 
	delete[] resultConvert;

當result也就是函數中定義的返回值有bstr*類型時,需要進行轉換,因爲cout無法直接輸出bstr類型的內容,需要先通過上面的第三行的轉換函數轉換爲一個字符數組然後再通過std::cout進行輸出,之所以沒有直接cout是因爲上面用了no_namepsace所以沒有定義using namespace std;

 

上述操作做完後直接生成然後執行就可以啦!如果有理解不到位的請各位指正,謝謝大家!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章