天天看點

Qt使用COM元件

一、先上僞代碼

#include <QAxObject>
#include <qt_windows.h>

bool Init(char cMode)
{
    QAxObject m_QAxObj;
    QVariantList params0;
	QString qresult;
    int engine_hand;
    HRESULT hres =  CoInitializeEx(0, COINIT_MULTITHREADED );

	if (hres != S_OK && hres != 0x80010106)
	{
		hres = CoInitializeEx( 0, COINIT_APARTMENTTHREADED );
		if (hres != S_OK && hres != 0x80010106)
		{
			qWarning("Qt:初始化Ole失敗(error %x)",(unsigned int)hres);
			return 0;
		}
	}
	b_re = m_QAxObj.setControl(QString::fromLocal8Bit("{7B3333C0-FDA0-11CE-8B06-444553540000}") );

	params0.clear();
	params0<<QVariant( 0 );
	params0<<QVariant( qresult );
    //int getHandle(int engin_type, QString &result)
	engine_hand = m_QAxObj.dynamicCall( "getHandle(QVariant)", params0 );
}
           

首先包含COM元件需要使用的兩個頭件。  CoInitializeEx()函數傳回的不一定是S_OK,因為如果在主程序中使用的話,元件初始化用QT預先調用了,這時傳回值是0x80010106,是以此兩種情況下都應該認識初始化成功。

調用COM伺服器的函數時,使用dynamicCall函數傳參數有兩種方法,一種是直接寫入參數,一種通過QVariantList 傳入參數,如果參數有通過引用方法傳回資料的時候,一定要用QVariantList方法。否則不能正确傳回值。同時要注意如上面的“getHandle”函數傳回結果字元串result不是直接放到QString qresult變量中,而是放到QVariantList params0變量中的。

二、元件導出函數說明

QT提供了列印COM元件函數說明方法,很強大,很好用

QString DOC = m_QAxObj.generateDocumentation();

	QFile outFile("d:/cmcengine.html");
	outFile.open(QIODevice ::ReadWrite | QIODevice ::Text);
	QTextStream TS(&outFile);

	TS<<DOC<<endl;
           

三、問題

1、一開始使用的時候遇個問題,就是第一次調用很好,第二次調用時就會出錯報:

中的 0x7c812afb 處最可能的異常: 0x000006BA: RPC 伺服器不可用
           

查了很久才終于發現,我的COM元件是線上程中調用的。第一次調用完就會結束線程,第二次調用重新開啟線程,這就導緻RPC伺服器不可用。如果第一次調用完不關閉線程,第二次調用直接使用剛才的線程繼續執行就不會出問題了。

2、在使用QT的過程中,使用QFileDialog::getOpenFileName()函數時,也會報KernelBase 第一機會處異常。但是程式沒有任何問題,正常執行。我使用的是VS2012和64位的win7系統。後來換成VS2015一樣錯誤。重裝系統,重裝vs都不能解決。百度說可以通過取消vs調試菜單中的異常--C++ EXceptions報警來取消這個報警,這個方法明顯是取消報警,但是沒有解決問題。我設定了一下,并沒有啟作用。仍然有這個報警。

     後來發現在另外一台win64位機器上,不會報這個警,但是并沒有發現這兩台機器有什麼不同。最終比較了一下這兩台機器的windows/system32檔案夾下的檔案,發現有問題的這台機器的kernelbase.dll檔案建立時間要早很多。沒有問題的這台機器的KernelBase.dll檔案是2019年的。償試着把新的這個KernelBase.dll檔案複制到有問題的這台機器上,因為有太多程式加載這個檔案了,沒辦法複制。這時不能不裝個某安全衛生,償試修複系統,在更新了一堆windows更新檔之後問題解決。

繼續閱讀