2010-06-10 114 views
23

我目前正在學習COM。我發現COM DLL是建立在傳統的DLL基礎上的。當我們構建COM DLL時,我們仍然依靠傳統的DLL導出方法來引導我們進入內部COM協同類。傳統DLL與COM DLL的區別

如果COM是用於二進制級別的組件重用,我認爲傳統的DLL可以達到同樣的效果。它們都暴露功能,它們都是二進制的,所以轉向COM方法有什麼意義?

目前,我有一種感覺,傳統的DLL公開方法在「」的方式,而COM DLL暴露出的「OOP」分層結構的方式方法。而面向對象的方式似乎是一種更好的方法。這是否能成爲COM盛行的原因?

非常感謝。

+1

是什麼讓你覺得COM盛行?如果更多的DLL是經典的'c'DLL而不是COM DLL,我不會感到驚訝。 – 2010-06-10 17:16:56

+0

感謝您的評論。也許我錯了。但是,似乎許多Windows功能都是基於COM構建的,比如ActiveX,OLE,甚至.NET也構建爲COM服務器的集合。所以我得出了這個結論。 – smwikipedia 2010-06-11 03:29:51

回答

28

不,這裏有很大的區別。 COM有一個定義良好的協議,用於創建對象,公開方法,管理內存,發佈類型信息,管理線程。幾乎沒有任何語言不支持使用COM服務器,不管它使用什麼語言編寫。

您不會直接暴露自己的功能。這可能僅適用於使用C/C++編寫的程序(因此它可以讀取頭文件),使用完全相同版本的C++編譯器進行編譯,並且不缺乏各種互操作問題。像暴露一個類似std :: string的C++類對象一樣簡單是不安全的。內存佈局不保證兼容,也沒有任何種類的內存所有權協議。

它可能是更多的OOPy,COM不支持繼承,因爲OOP很難在二進制級別兼容。這個問題需要運行時支持所有代碼購買到的虛擬機,如.NET和Java。

+1

關於第二段,有相當多的語言/框架等,它們允許您在C++之外使用本機(非COM)DLL。例如,.NET通過[P/Invoke](http://msdn.microsoft.com/en-us/magazine/cc164123.aspx)有一個簡單的使用interop機制。 – hemp 2010-06-22 00:34:41

+1

世界各不相同。 P/Invoke是一次一次呼叫一次的戰鬥。 COM服務器可以毫不費力地工作在95%的情況下。 – 2010-06-22 02:02:56

+0

什麼會被視爲服務潛在客戶端使用它的暴露com對象的「COM服務器」? – RollRoll 2017-06-23 17:13:00

12

COM DLL只是一個具有Com特定入口點的DLL。 COM公開了用於創建com對象的類工廠,因此需要有一種方法可以訪問由COM服務器實現的某個類工廠。這就是DllGetClassObject所做的。此外,COM DLL是自注冊的:他們可以通知Windows他們可用的類和接口。使DLL註冊的入口點是DllRegisterServer。

有幾個其他入口點,但他們沿着這些線。

如果DllRegisterServer沒有明確定義的入口點,則客戶端將無法使DLL自行註冊。這會使COM組件的安裝更加複雜。

如果沒有獲得類工廠的標準入口點,則每個DLL都必須定義自己的入口點,並且該信息必須放入Windows註冊表中,以便COM基礎結構知道如何訪問每個DLL的類工廠。沒有理由額外的複雜性,所以入口點也是標準化的。

至於COM與「C」不同的地方,主要區別在於契約的概念。 COM鼓勵程序員根據模塊之間的抽象接口思考問題,而不是分層的,自上而下的功能分解。這是一種'OOP',但是這個詞太寬鬆了,沒有多大用處,IMO。面向契約的方法的優點對於像C/C++這樣的強類型,靜態鏈接語言來說是多方面的。

5

如果你想了解的原因,引入COM和它背後的理念,我強烈建議閱讀From CPP to COM

7

我認爲通過閱讀基本COM的第一章你將有一個非常好的主意爲什麼使用COM。

簡單來說,COM確保二進制級別的兼容性,無論您使用何種語言,您使用的是哪種版本的編譯器。這不是關於「OOP」的事情,你肯定可以從DLL中暴露C++類,但它們不是「二進制兼容的」。

+0

您應該閱讀「Inside OLE」。 – gonzobrains 2014-03-18 02:41:36

4

關鍵的區別在於COM支持二進制兼容性。

如果您添加/刪除函數並重建傳統的DLL,那麼任何客戶端應用程序在嘗試使用DLL時可能會失敗,因爲它們是針對早期版本構建的。

COM引入了接口的概念,它是不可變的,所以不應該在構建之間進行更改等。每個COM對象都必須實現IUnknown接口,該接口包含QueryInterface方法,該方法用於向對象請求指向其他支持的接口。

COM規範確保IUnknown接口始終位於DLL中的相同位置,因此即使修改了對象以支持更多接口,仍可安全地調用QueryInterface方法。

3

想到COM的最好方法就是將它想象成你和使用你創建的對象的人之間的契約。

COM處理

  1. 如何版本的跨版本
  2. 對象如何發現你的對象,即使你的對象是在被重命名或從不同的源傳來一個DLL
  3. 如何引用並破壞你的對象(關於堆)
  4. 你期望的線程工作方式以及圍繞你的對象的線程/鎖定的規則

COM已經成爲一種標準,因爲雖然您可以製作一個傳統的DLL來處理上述每個項目,但在使用COM規則發送DLL時,您必須清楚說明預期的合同,此關係是爲你做的

你也正確的COM暴露對象,而更傳統的DLLS只是暴露功能。你經常會看到開發人員試圖直接在C中模擬COM中找到的契約,通常你會看到它們在DLL中克隆了COM的方面(例如,你會看到返回函數指針結構的方法)......我的經驗是如果你不使用COM來製作公共DLL,你會增加錯過某些情況的機率,尤其是當版本在圖片中時

+0

哦,我敢肯定我錯過了一些COM處理的東西 - 請注意他們作爲評論:-) – stuck 2010-06-21 02:46:54

5

DLL在Windows中有很多用途。許多類型的庫代碼都存儲在DLL中。例如,其中一個是.net程序集,這是一個不同的野獸。

COM DLL並不比「普通二進制PE DLL」更好,因爲COM DLL 也是普通DLL。使DLL成爲COM DLL的原因是,除了其他事情外,可能還會公開某些與某個契約(簽名)[查找條目IUnknown]相匹配的導出,甚至還有幾種標準化的接口[lookup entry'dual interface']只能實例化DLL中的特定對象,還能自動發現服務,包括函數名稱和參數類型。

雙接口,使它非常方便的鏈接到腳本語言(在網絡中使用,shell腳本,教育計劃等),因爲腳本程序員不關心嚴格類型。由COM DLL公開的雙重接口允許腳本運行時精確地查詢它期望的類型,並無縫地向用戶進行適當的強制轉換。這種靈活性允許構建一個完整的巨大COM基礎設施,包括組件註冊,DCOM(網絡調用)等。它使得將COM接口提供到Windows組件(例如WMI)和辦公室組件。 COM之上實現了許多其他常用接口,如ADO。

這一切都很好,但COM在任何意義上都不「佔上風」。 COM DLL是少數的DLL。普通的DLL和.NET DLL非常流行。微軟認爲.net接口優於COM。許多unix怪胎和其他人認爲dll是一個壞主意,因爲它不提供運行時鏈接服務,這與unix共享對象總是有同樣的意義。儘管是Windows開發人員,但我也認爲SO提供了一個更好的選擇,我希望只有一次。

2

除了已經發布的答案,COM接口的編程語言無關的方式,允許內存在一個進程的地址空間分配和釋放的另一個這些對象公開的二進制數據的對象。查找編組和解組。

它還允許而不注意編碼的細節,以確定空終止可能是要傳遞的字符串。 COM字符串被統計爲UNICODE字符串。

在IDL投擲和編譯類型庫到DLL,和你有自我描述接口。使用普通的DLL時,您必須從外部文檔瞭解它們具有的方法和參數。

COM標準也可以是跨平臺的。 Mac版本的Office支持COM,並且已經有類似Unix和類Unix系統的實現,儘管它們從未流行過。