微軟的COM中GUID和UUID、CLSID、IID
當(dāng)初微軟設(shè)計(jì)com規(guī)范的時(shí)候,有兩種選擇來(lái)保證用戶的設(shè)計(jì)的com組件可以全球唯一:
第一種是采用和Internet地址一樣的管理方式,成立一個(gè)管理機(jī)構(gòu),用戶如果想開(kāi)發(fā)一個(gè)COM組件的時(shí)候需要向該機(jī)構(gòu)提出申請(qǐng),并交一定的費(fèi)用。
第二種是發(fā)明一種算法,每次都能產(chǎn)生一個(gè)全球唯一的COM組件標(biāo)識(shí)符。
第一種方法,用戶使用起來(lái)太不方便,微軟采用第二種方法,并發(fā)明了一種算法,這種算法用GUID(Globally Unique Identifiers)來(lái)標(biāo)識(shí)COM組件,GUID是一個(gè)128位長(zhǎng)的數(shù)字,一般用16進(jìn)制表示。算法的核心思想是結(jié)合機(jī)器的網(wǎng)卡、當(dāng)?shù)貢r(shí)間、一個(gè)隨即數(shù)來(lái)生成GUID。從理論上講,如果一臺(tái)機(jī)器每秒產(chǎn)生10000000個(gè)GUID,則可以保證(概率意義上)3240年不重復(fù)。
GUID的例子: 54BF6567--1007--11D1--B0AA--444553540000
HKEY_CLASSES_ROOT\CLSID\{002B9E07-2E10-438F-AF1E-40E6A96F1EE4}
在微軟的COM中GUID和UUID、CLSID、IID是一回事,只不過(guò)各自代表的意義不同:
UUID : 代表COM
CLSID : 代表COM組件中的類
IID :代表COM組件中的接口
在程序中,實(shí)際對(duì)象數(shù)據(jù)對(duì)應(yīng)的處理程序路徑string往往不盡相同,比如有的放C盤(pán)有的D盤(pán),微軟想出了一個(gè)解決方案,那就是不使用直接的路徑表示方法,而使用一個(gè)叫 CLSID的方式間接描述這些對(duì)象數(shù)據(jù)的處理程序路徑。
CLSID 其實(shí)就是一個(gè)號(hào)碼,CLSID 的結(jié)構(gòu)定義如下:
typedef struct _GUID {
DWORD Data1; // 隨機(jī)數(shù)
WORD Data2; // 和時(shí)間相關(guān)
WORD Data3; // 和時(shí)間相關(guān)
BYTE Data4[8]; // 和網(wǎng)卡MAC相關(guān)
} GUID;
typedef GUID CLSID; // 組件ID
typedef GUID IID; // 接口ID
#define REFCLSID const CLSID &
// 常見(jiàn)的聲明和賦值方法
CLSID CLSID_Excel = {0x00024500,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}};
struct __declspec(uuid("00024500-0000-0000-C000-000000000046")) CLSID_Excel;
class DECLSPEC_UUID("00024500-0000-0000-C000-000000000046") CLSID_Excel;
// 注冊(cè)表中的表示方法
{00024500-0000-0000-C000-000000000046}
如果使用開(kāi)發(fā)環(huán)境編寫(xiě)組件程序,則IDE會(huì)自動(dòng)幫你產(chǎn)生 CLSID;
可以用函數(shù) CoCreateGuid() 產(chǎn)生 CLSID;
使用"vc目錄\Common\Tools\GuidGen.exe"工具產(chǎn)生GUID
每一個(gè)COM組件都需要指定一個(gè) CLSID,并且不能重名。它之所以使用16個(gè)字節(jié),就是要從概率上保證重復(fù)是“不可能”的。但是,微軟為了使用方便,也支持另一個(gè)字符串名稱方式,叫 ProgID。。由于 CLSID 和 ProgID 其實(shí)是一個(gè)概念的兩個(gè)不同的表示形式,所以我們?cè)诔绦蛑锌梢噪S便使用任何一種。
下面是 CLSID 和 ProgID 之間的轉(zhuǎn)換方法和相關(guān)的函數(shù):
函數(shù) |
功能說(shuō)明 |
CLSIDFromProgID()、CLSIDFromProgIDEx() |
由 ProgID 得到 CLSID。沒(méi)什么好說(shuō)的,你自己都可以寫(xiě),查注冊(cè)表貝 |
ProgIDFromCLSID() |
由 CLSID 得到 ProgID,調(diào)用者使用完成后要釋放 ProgID 的內(nèi)存(注5) |
CoCreateGuid() |
隨機(jī)生成一個(gè) GUID |
IsEqualGUID()、IsEqualCLSID()、IsEqualIID() |
比較2個(gè)ID是否相等 |
StringFromCLSID()、StringFromGUID2()、StringFromIID() |
由 CLSID,IID 得到注冊(cè)表中CLSID樣式的字符串,注意釋放內(nèi)存 |
客戶端軟件和組件之間的調(diào)用如下:
容器 協(xié)商部分 |
組件 應(yīng)答部分 |
|
1 |
根據(jù)CLSID啟動(dòng)組件 。 CoCreateInstance() |
生成對(duì)象,執(zhí)行構(gòu)造函數(shù),執(zhí)行初始化動(dòng)作。 |
2 |
你有IUnknown接口嗎? |
有,給你! |
3 |
恩,太好了,那么你有IPersistStorage接口嗎?(注9) IUnknown::QueryInterface(IID_IPersistStorage...) |
沒(méi)有! |
4 |
真差勁,連這個(gè)都沒(méi)有。那你有IPersistStreamInit接口嗎?(注10) IUnknown::QueryInterface(IID_IPersistStreamInit...) |
哈,這個(gè)有,給! |
5 |
好,好,這還差不多。你現(xiàn)在給我初始化吧。 IPersistStreamInit::InitNew() |
OK,初始化完成了。 |
6 |
完成了?好!現(xiàn)在你讀數(shù)據(jù)去吧。 IPersistStreamInit::Load() |
讀完啦。我根據(jù)數(shù)據(jù),已經(jīng)在窗口中顯示出來(lái)了。 |
7 |
好,現(xiàn)在咱們各自處理用戶的鼠標(biāo)、鍵盤(pán)消息吧...... |
...... |
8 |
哎呀!用戶要保存退出程序了。你的數(shù)據(jù)被用戶修改了嗎? IPersistStreamInit::IsDirty() |
改了,用戶已經(jīng)修改啦。 |
9 |
那好,那么用戶修改后,你的數(shù)據(jù)需要多大的存儲(chǔ)空間呀? IPersistStreamInit::GetSizeMax() |
恩,我算算呀......好了,總共需要500KB。 |
10 |
暈,你這么個(gè)小玩意居然占用這么大空間?!......好了,你可以存了。 IPersistStreamInit::Save() |
謝謝,我已經(jīng)存好了。 |
11 |
恩。拜拜了您那。(注11) IPersistStreamInit::Release();IUnknown::Release() |
執(zhí)行析構(gòu)函數(shù),刪除對(duì)象。 |
12 |
我自己也該退出了...... PostQuitMessage() |
本文僅代表作者觀點(diǎn),版權(quán)歸原創(chuàng)者所有,如需轉(zhuǎn)載請(qǐng)?jiān)谖闹凶⒚鱽?lái)源及作者名字。
免責(zé)聲明:本文系轉(zhuǎn)載編輯文章,僅作分享之用。如分享內(nèi)容、圖片侵犯到您的版權(quán)或非授權(quán)發(fā)布,請(qǐng)及時(shí)與我們聯(lián)系進(jìn)行審核處理或刪除,您可以發(fā)送材料至郵箱:service@tojoy.com

