1. 程式人生 > >COM技術入門(2)

COM技術入門(2)

C++ com

一、IDispatch接口與Variant類型

1.IDispatch的簡介與作用

a) 自動化技術讓解釋下語音能夠調用到自定義的接口,

b) 具有自動化功能的組件是支持IDispatch接口的COM組件

c) IDispatch能夠接收一個函數的字符串名稱,並執行這個函數.

d) 解釋性語言要調用COM組件的自定義接口都是通過自動化控制

程序把自定義接口中的函數的字符串和參數傳遞給IDispatch

而IDispatch間接的執行自定義接口中的函數.

e) 重要的函數 GetIDsOfNames和Invoke

GetIDsOfNames函數將讀取一個函數名稱,並返回其調用ID,

Invoke函數接收一個調度ID,跟函數參數,執行調用ID所對應函數功能.

f) 所以解釋下語音跟宏語音不必直接認識我們的自定義接口,

只要我們的COM組件支持了IDispatch接口,他們就能通過自動化控制

程序調用我們的IDispatch接口,通過傳入函數名字的字符串

和函數參數來執行調用我們的自定義接口.



2.常用的COM數據類型

a)基本類型

CHAR typedef char CHAR CHAR* char指針

BYTE 無符號的char BYTE*

SHORT typedef short SHORT SHORT*

USHORT 無符號short USHORT*

INT typedef int INT*

UINT 無符號int UINT*

LONG typedef long LONG*

ULONG 無符號long ULONG*

FLOAT FLOAT*

DOUBLE DOUBLE*

VARIANT_BOOL COM中的布爾類型 typedef short VARIANT_BOOL

註意: 0== FALSE -1== TRUE

VARIANT_BOOL*

b) 字符串

BSTR COM中的字符串類型

BSTR* BSTR指針

BSTR是指向的是寬字符串的指針,是一個帶有

字符計數值的字符串,且這個計數值是保存在字符數組的開頭

技術分享圖片


3.BSTR基本操作

a) 錯誤賦值 BSTR str = L"ABCD";

這樣是錯誤的,因為字符串前面沒有計數值

b)BSTR SysAllocString(const OLECHAR*)

是COM申請BSTR字符串的方法,把CHAR* 傳進去,返回BSTR類型

c)BSTR SysAllocStringLen(const OLECHAR* ,UINT)

根據字符串指針與字符個數構造BSTR字符串

d)UINT SysStringLen(BSTR)獲取字符串計數值

e)void SysFreeString(BSTR)釋放字符串,當COM中的

字符串(BSTR)不再使用後,調用該函數.

BSTR strA = SysAllocString(L"Hello"); //申請一個字符串

//申請指定個數字符串,從參數1中取

BSTR strB = SysAllocStringLen(strA,SysStringLen(strA));

SysFreeString(strA);

SysFreeString(strB);



4.COM常用數據類型

IUnknown* COM的最基本的接口指針

IUnknown** 指針的指針

IDispatch* 支持組件自動化的接口

IDispatch** IDispatch*的指針

如果寫的組件不想被 解釋性的語言 腳本語言

查找接口的話, 可以直接使用IUnknown接口



5.萬能數據類型 VARIANT

a) 具備跨語言的特性,同時能存儲任何的數據類型

為了實現這個類型的功能,C++中這個類型是一個結構體,

這個結構體,裏面又有聯合體,聯合多種基本數據類型

又有變量類型標誌VARTYPE vt.標誌他的類型


b) 初始化和清楚

	VARIANT var;
	VariantInit(&var);
	//此時var.vt == VT_EMPTY控件
	//..其他操作
	//清除操作
	VariantClear(&var);


c) VARIANT的使用

用VARIANT保存LONG類型

	VARIANT var;
	VariantInit(&var);
	//此時var.vt == VT_EMPTY控件
	//..其他操作
	//清除操作
	//VT_I4  ×××就是VT_I2
	var.vt = VT_I4;
	//賦值
	var.lVal = 100;
	VariantClear(&var);

FLOAT類型 VT_R4 DOUBLE VT_R8

var.fltVal flaot值


VARIANT使用BSTR類型

var.vt = VT_BSTR;

var.bstrVal = SysAllocString(L"HEllo");


VT_BOOL 布爾類型


d) 讀取值

//先判斷類型 在根據類型讀取

if(var.vt == VT_l4)
{

LONG lValue = var.lVar;

}





6.COM數據類型的轉換

LONG轉換成FLOAT

VARIANT var; 初始化

var.vt = VT_I4;

var.lVar = 100;

VariantChangeType(&var,&var,0,VT_R4);

if(var.vt = VT_R4)

{

LONG fValue = var.fltValue;

}

清空var




7.VARIANT類型的派生類

a) 在派生類擴展VARIANT類使得他的使用更加方便

#include <atlbase.h>ATL庫裏面就帶有一個派生類CComVariant

他簡化了初始化和清楚, 構造函數可以直接傳遞基本類型或者VARIANT類型

可以用C++的類型,也可以用COM基本類型來構造一個對象

	INT a = 10;
	CComVariant b(a);
	
	double c = 100.0100;
	CComVariant d(c);

b) 賦值 重載了運算符 operator= 根據不同類型分配不同值

也就是說如果你是INT型 直接對象=值 d = 100;







(二)、測試簡單對象


一、ATL制作簡單對象(Simple Object)

技術分享圖片

技術分享圖片

完成即可

技術分享圖片

1.項目創建完成,添加簡單對象(Simple Object)

技術分享圖片

選擇簡單對象

技術分享圖片


輸入簡稱

技術分享圖片


ProgId

ATLProject.HelloSimpleObject

ProgID是程序員給某個CLSID指定一個程序員易記的名稱,

某些計算機語言通過PropID來標記組件 命名規則

<Program>.<Component>.<Version>

程序.組件.版本



技術分享圖片

雙重是支持IDispatch接口的,這樣這個接口就會支持一些腳本語言等等。




2.給簡單對象添加一個方法,

在類視圖選中剛添加的這個(選中接口不是添加的類)然後添加方法

技術分享圖片

技術分享圖片

接口方法是固定的HRESULT,所以只能用輸入的參數作為返回值.

技術分享圖片in代表輸入


加一個指針就可以顯示out,表示是輸出的可作為返回值

retval表示用他做返回值

技術分享圖片



這個ID表示這個方法 在接口裏的ID,直接點擊完成即可

技術分享圖片



3.來到解決方案管理器查看項目ild文件

技術分享圖片


ATLProjectLib的uuid

技術分享圖片


組件的UUID他被ATLProjectLib包含,組件又包含了這個 我們自定義的接口

技術分享圖片

會發現我們的組件(簡單對象就是組件)支持我們自定義接口(IHelloSimpleObject)


接口定義上面會看到接口IID,

技術分享圖片

而且接口裏就有一個我們剛創建的方法, 他的ID是1




4.方法的聲明和實現

在.h文件裏聲明了

技術分享圖片

在.c文件裏實現了

技術分享圖片



5.添加屬性

他會自動給這個屬性添加 SET和GET方法,

ProPutRef表示為引用參數

技術分享圖片

技術分享圖片

添加屬性方法ID自增



6.編譯生成

除了dll文件還生成了兩個代碼文件(ATLProject_i.h和 _i.c)

這兩個文件裏面描述的是組件的相關信息,如接口方法接口iid,組件CLSID


7.組件的CLSID

組件的CLSID和IID一樣,都是GUID,

組件的CLSID用於標識組件,每一個組件都有一個與之對應的CLSID

紅色就是組件名,上面就是他的CLSID

技術分享圖片


這個就是你輸入的組件名

技術分享圖片




二、在MFC中測試簡單對象

直接創建一個對話框程序

stdafx.h添加 _i.h文件 stdafx.cpp 添加_h.c文件

技術分享圖片

技術分享圖片

測試代碼

組件這些都被宏定義了,使用更方便

技術分享圖片


	HRESULT hr = E_FAIL;
	//使用COM組件必須初始化
	hr = CoInitialize(NULL);
	if(SUCCEEDED(hr))
	{
		//接口指針對象
		IHelloSimpleObject* pHello = NULL;
		//創建接口指針實例  組件對象
		//第一個參數是組件標識
		//第二個參數NULL
		//第三個參數一般用這個CLSCTX_INPROC_SERVER 
		//第四個參數接口標識符
		//第五個參數 接口指針 返回
		hr = CoCreateInstance(CLSID_HelloSimpleObject,NULL,CLSCTX_INPROC_SERVER,
			IID_IHelloSimpleObject,(LPVOID*)&pHello);

		if(SUCCEEDED(hr))
		{
			LONG sum = 0;
			hr = pHello->SumLong(100,100,&sum);

			//讀取描述
			BSTR bstrs = SysAllocString(L"");
			hr = pHello->get_m_desc(&bstrs);
			SysAllocString(bstrs);
			bstrs = NULL;

			//寫入
			BSTR strb = SysAllocString(L"MFC中測試");
			hr = pHello->put_m_desc(strb);
			SysAllocString(strb);
			bstrs = NULL;

			bstrs = SysAllocString(L"");
			hr = pHello->get_m_desc(&bstrs);
			SysAllocString(bstrs);
			bstrs = NULL;
		}

		//接口不再使用
		pHello->Release();
	}

	//不再使用com組件對象時 一般放在程序結束
	CoUninitialize();













COM技術入門(2)