寬屏網站尺寸營銷型網站制作
在介紹C++和winrt與COM組件技術的關系之前,有必要介紹一下com組件技術,這項技術比較古老,但是它一直作為windows的基石存在。COM 是一類獨立于平臺且面向對象的分布式系統(tǒng),用于創(chuàng)建可交互的二進制軟件組件。 COM 技術是 Microsoft OLE(復合文檔)和 ActiveX(支持 Internet 的組件)技術的基礎。
注意我們僅僅介紹基礎的COM組件技術,而不是全面的覆蓋這項技術,講述這項技術是一項非常困難的工作,所以許多知識點我們只是提及,不會深究,我個人比較推薦的書是《com組件論》,這本書非常值得一看。
COM技術被認為是C++進階的高級技術,它從本質上解釋了接口和實現,但是由于COM編程過于復雜,并且COM技術本質上windows使用的技術,所以慢慢的它被隱藏到系統(tǒng)深處了。
組件對象模型
Microsoft 組件對象模型 (COM) 是一個獨立于平臺的面向對象的分布式系統(tǒng),可用于創(chuàng)建可以交互的二進制軟件組件。 COM 技術是 Microsoft OLE(復合文檔)和 ActiveX(支持 Internet 的組件)以及其他組件的基礎技術。
要理解 COM(以及所有基于 COM 的技術),關鍵是要理解它不是一種面向對象的語言,而是一種標準。 COM 也沒有指定應用程序的結構;語言、結構和實現細節(jié)留給應用程序開發(fā)人員。 相反,COM 指定對象模型和編程要求,使 COM 對象(也稱為 COM 組件,有時簡稱為對象)能夠與其他對象進行交互。 這些對象可以在單個進程中,也可以在其他進程中,甚至可以在遠程計算機上。 它們可以以不同的語言編寫,并且它們在結構上可能大相徑庭,這就是為什么 COM 被稱為二進制標準的原因;在程序轉換為二進制計算機代碼后應用的標準。
COM 唯一的語言要求是,代碼是用一種可以創(chuàng)建指針結構并通過指針顯式或隱式調用函數的語言生成的。 面向對象的語言(如 C++ 和 Smalltalk)提供簡化 COM 對象的實現的編程機制,而 C、Java 和 VBScript 等語言可用于創(chuàng)建和使用 COM 對象。
COM 定義 COM 對象的基本性質。 通常,軟件對象由一組數據和操作數據的函數組成。 COM 對象是專門通過一組或多組相關函數來訪問對象數據的對象。 這些函數集被稱為接口,接口的函數被稱為方法。 此外,COM 要求訪問接口方法的唯一方法是通過指向接口的指針。
除了指定基本的二進制對象標準外,COM 還定義了某些基本接口,這些接口提供了所有基于 COM 的技術所共有的功能,并提供了所有組件所需的少量功能。 COM 還定義了對象如何在分布式環(huán)境中協(xié)同工作,并添加了安全功能來幫助提供系統(tǒng)和組件完整性。
COM 簡介
Microsoft 組件對象模型 (COM) 定義了二進制互操作性標準,可利用此標準創(chuàng)建在運行時交互的可重用軟件庫。 無需將 COM 庫編譯到應用程序中即可使用 COM 庫。 COM 是許多 Microsoft 產品和技術的基礎,例如 Windows Media Player 和 Windows Server。
COM 定義適用于許多操作系統(tǒng)和硬件平臺的二進制標準。 對于網絡計算,COM 定義了標準線路格式和協(xié)議,用于在不同硬件平臺上運行的對象之間交互。 COM 獨立于實現語言,這意味著可以使用不同的編程語言(如 C++ 和 .NET Framework 中的編程語言)創(chuàng)建 COM 庫。
COM 規(guī)范提供了啟用跨平臺軟件重用的所有基本概念:
- 組件之間的函數調用的二進制標準;
- 用于將函數強類型分組到接口中的預配;
- 提供多態(tài)性、功能發(fā)現和對象生存期跟蹤的基接口;
- 唯一標識組件及其接口的機制;
- 從部署創(chuàng)建組件實例的組件加載程序;
COM 有許多部件協(xié)同工作,從而支持創(chuàng)建從可重用組件生成的應用程序:
- 提供符合 COM 規(guī)范的運行時環(huán)境的主機系統(tǒng);
- 定義功能協(xié)定的接口和實現接口的組件;
- 向系統(tǒng)提供組件的服務器和使用組件提供的功能的客戶端;
- 用于跟蹤組件在本地和遠程主機上的部署位置的注冊表;
- 用于找到本地和遠程主機上的組件并將服務器連接到客戶端的服務控制管理器;
- 定義如何在主機文件系統(tǒng)上導航文件內容的結構化存儲協(xié)議;
啟用跨主機和平臺的代碼重用是 COM 的核心。 可重用接口實現命名為組件、組件對象或 COM 對象。 一個組件實現一個或多個 COM 接口。
通過設計庫實現的接口,可定義自定義 COM 庫。 庫的使用者無需了解庫的部署和實現詳細信息即可發(fā)現和使用其功能。
對象和接口
COM 對象通過接口公開其功能,接口是成員函數的集合。 COM 接口定義組件的預期行為和職責,并指定一個強類型協(xié)定,該協(xié)定提供一小組相關操作。 COM 組件之間的所有通信都通過接口進行,并且通過組件接口公開組件提供的所有服務。 調用方只能訪問接口成員函數。 除非在接口中公開內部狀態(tài),否則調用方無法使用內部狀態(tài)。
接口是強類型。 每個接口都有自己的唯一接口標識符(名為 IID),這樣就消除了與人類可讀名稱可能發(fā)生的沖突。 IID 是全局唯一標識符 (GUID),此標識符與開放軟件基金會 (OSF) 分布式計算環(huán)境 (DCE) 定義的通用唯一 ID (UUID) 相同。 創(chuàng)建新接口時,必須為該接口創(chuàng)建新的標識符。 當調用方使用接口時,它必須使用唯一標識符。 此顯式標識可消除會導致運行時失敗的命名沖突,從而提高穩(wěn)健性。
定義新接口時,可以使用接口定義語言 (IDL) 創(chuàng)建接口定義。 從此接口定義中,Microsoft IDL 編譯器會生成標頭文件供使用接口的應用程序使用,并生成源代碼來處理遠程過程調用。 Microsoft 提供的 IDL 基于 DCE IDL 的簡單擴展,這是基于遠程過程調用 (RPC) 的分布式計算的行業(yè)標準。 IDL 是可方便接口設計人員的工具,不是 COM 互操作性的核心。 使用 IDL 時,無需為每個編程環(huán)境手動創(chuàng)建標頭文件。
在 COM 接口中很少使用繼承。 COM 僅支持接口繼承以重用與基接口關聯(lián)的協(xié)定。 COM 不支持選擇性繼承;因此,如果一個接口繼承自另一個接口,則它包括基接口定義的所有函數。 此外,接口僅使用單重繼承而不是多重繼承從基接口獲取函數。
接口實現
不能單獨創(chuàng)建 COM 接口的實例。 而是創(chuàng)建實現接口的類實例。 在 C++ 中,COM 接口建模為抽象基類,這意味著接口是僅包含純虛擬成員函數的 C++ 類。 C++ 庫會從一個或多個接口繼承成員函數簽名、覆蓋每個成員函數并為每個函數提供實現,從而實現 COM 對象。
可以使用任何支持函數指針概念的編程語言來實現 COM 接口。 例如,在 C 中,接口是一個結構,其中包含指向函數指針表的指針,此結構用于接口中的每個方法。
實現接口時,類必須為接口中的每個函數提供實現。 如果類在接口函數中無事可做,則實現可以是單個 return 語句。
COM 類可使用唯一的 128 位類 ID (CLSID) 標識,該 ID 將類與文件系統(tǒng)中的特定部署相關聯(lián),對于 Windows 而言這是 DLL 或 EXE。 CLSID 是 GUID,這意味著沒有其他類具有相同的 CLSID。 使用唯一類標識符可防止類之間發(fā)生名稱沖突。 例如,兩個不同的供應商可以編寫名為 CStack 的類,但兩個類都具有唯一的 CLSID,因此可避免出現任何沖突。
可以使用 CoCreateGuid 函數或使用在內部調用此函數的 COM 創(chuàng)作工具(如 Visual Studio)獲取新的 CLSID。
IUnknown 接口
所有 COM 接口都繼承自 IUnknown 接口。 IUnknown 接口包含基本 COM 操作,可實現多態(tài)性和用于實例生存期管理。 IUnknown 接口有三個成員函數,名為 QueryInterface、AddRef 和 Release。 要實現 IUnknown 接口,需要所有 COM 對象。
QueryInterface 成員函數為 COM 提供多態(tài)性。 調用 QueryInterface 以在運行時確定 COM 對象是否支持特定接口。 如果 COM 對象實現請求的接口,則返回 ppvObject 參數中的接口指針,否則返回 NULL。 QueryInterface 成員函數支持在 COM 對象支持的所有接口之間導航。
COM 對象實例的生存期由其引用計數控制。 IUnknown 成員函數 AddRef 和 Release 控制計數。 AddRef 會遞增計數,而 Release 會遞減計數。 當引用計數達到零時,Release 成員函數可能會釋放實例,因為沒有調用方在使用它。
客戶端/服務器模型
一個 COM 類可實現許多 COM 接口。 實現由調用方與 COM 類實例交互時運行的二進制文件組成。 COM 支持在不同應用程序中使用類,包括在不了解特定類的情況下編寫的應用程序。 在 Windows 平臺上,類存在于動態(tài)鏈接庫 (DLL) 或其他應用程序 (EXE) 中。
在其主機系統(tǒng)上,COM 維護系統(tǒng)上安裝的 COM 對象的所有 CLSID 的注冊數據庫。 注冊數據庫是每個 CLSID 與存放相應類的 DLL 或 EXE 的位置之間的映射。 只要調用方想要創(chuàng)建 COM 類的實例,COM 就會查詢此數據庫。 調用方只需知道 CLSID 即可請求類的新實例。
COM 對象與其調用方之間的交互建模為客戶端/服務器關系。 客戶端是從系統(tǒng)請求 COM 對象的調用方,而服務器是存放向客戶端提供服務的 COM 對象的模塊。
COM 客戶端是將 CLSID 傳遞給系統(tǒng)以請求 COM 對象實例的任何調用方。 創(chuàng)建實例的最簡單方法是調用 COM 函數 CoCreateInstance。
CoCreateInstance 函數會創(chuàng)建指定 CLSID 的一個實例,并返回客戶端所請求類型的接口指針。 客戶端負責管理實例的生存期,方法是在客戶端使用完實例后調用其 Release 函數。 若要根據單個 CLSID 創(chuàng)建多個對象,請調用 CoGetClassObject 函數。 若要連接到已創(chuàng)建且正在運行的對象,請調用 GetActiveObject 函數。
COM 服務器向系統(tǒng)提供 COM 實現。 服務器將 CLSID 與 COM 類相關聯(lián),存放類的實現,實現用于創(chuàng)建類實例的類工廠,并可用于卸載服務器。
COM 服務器與提供給系統(tǒng)的 COM 對象不同。
若要啟用創(chuàng)建 COM 對象,COM 服務器必須提供 IClassFactory 接口的實現。 客戶端可以調用 CreateInstance 方法,以請求 COM 對象的新實例,但通常將此類請求封裝在 CoCreateInstance 函數中。
可以將 COM 服務器部署為在運行時加載到客戶端進程中的共享庫(Windows 平臺上的 DLL),或部署為可執(zhí)行模塊(Windows 平臺上的 EXE)。