• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-250  評論-20  文章-55  trackbacks-0
            COM

            第1章 組件

            1、COM,即組件對象模型,是關(guān)于如何建立組件以及如何通過組件建構(gòu)應(yīng)用程序的一個規(guī)范。
            2、組件的優(yōu)點:應(yīng)用程序可隨時間的流逝而發(fā)展變化;定制應(yīng)用程序;組件庫;分布式組件。
            3、對組件的需求:組件必須動態(tài)連接;必須隱藏其內(nèi)部實現(xiàn)細(xì)節(jié)。
            4、COM組件是以Win32動態(tài)鏈接庫(DLLs)或可執(zhí)行文件(EXEs)的形式發(fā)布的可執(zhí)行代碼組成

            的。遵循COM規(guī)范編寫的組件將能夠滿足對組件家夠的所有需求。COM組件是動態(tài)鏈接的,COM使

            用DLL將組件動態(tài)鏈接起來。對于COM組件的封裝是很容易的。COM組件按照一種標(biāo)準(zhǔn)的方式來宣

            布他們的存在。COM組件是一種給其他應(yīng)用程序提供面向?qū)ο蟮腁PI或服務(wù)的極好方法。
            5、COM并不是一種計算機(jī)語言。
            6、將COM同DLL相提并論是不合適的。實際上COM使用了DLL來給組件提供動態(tài)鏈接的能力。
            7、COM并不是像Win32API那樣的函數(shù)集,它更主要的是一種編寫能夠按面向?qū)ο驛PI形式提供服

            務(wù)的組件的方法。
            8、COM并不是類似于MFC這樣的C++類庫。COM給開發(fā)人員提供的是一種開發(fā)與語言無關(guān)的組件庫

            的方法,但COM本身并沒有提供任何實現(xiàn)。
            9、COM具有一個被稱作是COM庫的API,它提供的是對所有客戶及組件都非常有用的組件管理服務(wù)

            ////////////////////////////////////////////////////////////////////

            第2章 接口

            1、在COM中接口就是一切。
            (1)接口可以保護(hù)系統(tǒng)免首外界變化的影響。
            (2)接口可以使客戶用同樣的方式來處理不同的組件。
            2、(1)COM接口在C++中是用純抽象基類實現(xiàn)的。
            ?? (2)一個COM組件可以提供多個接口。
            ?? (3)一個C++類可以使用多繼承來實現(xiàn)一個可以提供多個接口的組件。
            3、類并非組件。
            4、接口并非總是繼承的。對接口的繼承只不過是一種實現(xiàn)細(xì)節(jié)而已。除了可以使用一個類來實

            現(xiàn)幾個不同的接口外,還可以用單個的類來實現(xiàn)每一個接口再使用指向這些類的指針。
            5、組件可以支持任意數(shù)目的接口。為支持多重接口,可以使用多重繼承。支持多重接口的組件

            可以被看作是接口的集合。
            6、COM接口的不變性、多態(tài)以及接口繼承。
            (1)一旦公布了一個接口,那么它將永遠(yuǎn)保持不變。當(dāng)對組件進(jìn)行升級時,一般不會修改已有

            的接口,而是加入一些新的接口。
            (2)多態(tài)指的是可以按同一種方式來處理不同的對象。
            7、虛擬函數(shù)表(vtbl):包含一組指向虛擬函數(shù)實現(xiàn)的指針。
            定義一個純抽象基類也就是定義了相應(yīng)的內(nèi)存結(jié)構(gòu)。但此內(nèi)存只是在派生類中實現(xiàn)此抽象基類時

            才會被分配。當(dāng)派生類繼承一個抽象基類時,它將繼承此內(nèi)存結(jié)構(gòu)。
            8、在COM中,對一個組件的訪問只能通過函數(shù)完成,而絕不能直接通過變量。

            9、接口的真正的威力在于繼承此接口的所有類均可以被客戶按同一方式進(jìn)行處理。


            ////////////////////////////////////////////////////////////


            第3章 QueryInterface函數(shù)


            1、接口查詢:
            客戶同組件的交互都是通過一個接口完成的。在客戶查詢組件的其他接口時,也是通過接口完成

            的。這個接口就是IUnknown。
            IUnknown接口的定義包含在Win32 SDK中的UNKNOWN.H頭文件中。
            interface IUnknown
            {
            ??? virtual HRESULT _stdcall QueryInterface(const IID& iid,void **ppv) = 0;
            ??? virtual ULONG _stdcall AddRef() = 0;
            ??? virtual ULONG _stdcall Release() = 0;
            }
            在IUnknown中定義了一個名為QueryInterface的函數(shù)。客戶可以調(diào)用QueryInterface來決定組件

            是否支持某個特定的接口。
            2、所有的COM接口都需要繼承IUnknown。
            3、由于所有的COM接口都繼承了IUnknown,每個接口的vtbl中的前三個函數(shù)都是

            QueryInterface,AddRef和Release。若某個接口的vtbl中的前三個函數(shù)不是這三個,那么它將不

            是一個COM接口。由于所有的接口都是從IUnknown 繼承的,因此所有的接口都支持

            QueryInterface.因此組件的任何一個接口都可以被客戶用來獲取它所支持的其他接口。
            4、非虛擬繼承:注意IUnknown并不是虛擬基類,所以COM接口并不能按虛擬方式繼承IUnknown,

            這是由于會導(dǎo)致與COM不兼容的vtbl。若COM接口按虛擬方式繼承IUnknown,那么COM接口的vtbl

            中的頭三個函數(shù)指向的將不是IUnknown的三個成員函數(shù)。
            5、一個QuertyInterface可以用一個簡單的if-then-else語句實現(xiàn),但case語句是無法用的,因

            為接口標(biāo)識符是一個結(jié)構(gòu)而不是一個數(shù)。
            6、多重類型及類型轉(zhuǎn)換
            7、QueryInterface的規(guī)則
            (1)QueryInterface返回的總是同一IUnknown指針。
            (2)若客戶曾經(jīng)獲取過某個接口,那么它將總能獲取此接口。
            (3)客戶可以再次獲取已經(jīng)擁有的接口。
            (4)客戶可以從任何接口返回到起始接口。
            (5)若能夠從某個借口獲取某特定接口,那么可以從任意接口都將可以獲取此接口。
            8、接口的IID決定了它的版本。當(dāng)改變了下列條件中的任何一個時,就應(yīng)給新接口指定新的ID:
            (1)接口中函數(shù)的數(shù)目。
            (2)接口中函數(shù)的是順序。
            (3)某個函數(shù)的參數(shù)。
            (4)某個函數(shù)參數(shù)的順序。
            (5)某個函數(shù)參數(shù)的類型。
            (6)函數(shù)可能的返回值。
            (7)函數(shù)參數(shù)的含義。
            (8)接口中函數(shù)的含義。
            9、避免違反隱含和約:
            (1)使接口不論在其成員函數(shù)怎么被調(diào)用都能正常工作。
            (2)強(qiáng)制客戶按一定的方式來使用此接口并在文檔中將這一點說明清楚。

            //////////////////////////////////////////////////////////////////

            第4章 引用計數(shù)

            1、生命期控制
            IUnknown的另外兩個成員函數(shù)AddRef和Release的作用就是給客戶提供一種讓它指示何時處理完

            一個接口的手段。
            2、AddRef和Release實現(xiàn)的是一種名為引用計數(shù)的內(nèi)存管理技術(shù)。
            引用計數(shù)是使組件能夠自己將自己刪除的最簡單同時也是效率最高的方法。
            COM組件將維護(hù)一個稱做是引用計數(shù)的數(shù)值。當(dāng)客戶從組件取得一個接口時,此引用計數(shù)值將增1

            。當(dāng)客戶使用完某個接口后,組件的引用計數(shù)值將減1。當(dāng)引用計數(shù)值為0時,組件即可將自己從

            內(nèi)存中刪除。
            3、正確使用引用計數(shù)規(guī)則:
            (1)在返回之前調(diào)用AddRef。對于那些返回接口指針的函數(shù),在返回之前應(yīng)用相應(yīng)的指針調(diào)用

            AddRef。這些函數(shù)包括QueryInterface及CreateInstance。這樣當(dāng)客戶從這種函數(shù)得到一個接口

            后,它將無需調(diào)用AddRef。
            (2)在使用完接口之后調(diào)用Release。在使用完某個接口之后應(yīng)調(diào)用此接口的Release函數(shù)。
            (3)在賦值之后調(diào)用AddRef。在將一個接口指針賦給另外一個接口指針時,應(yīng)調(diào)用AddRef。換

            句話說,在建立接口的另外一個引用之后應(yīng)增加相應(yīng)組件的引用計數(shù)。
            4、在客戶看來,引用計數(shù)是處于接口級上而不是組件級上的。
            5、為什么選擇為每一個接口單獨維護(hù)一個引用計數(shù)而不是針對整個組件維護(hù)引用計數(shù)?(1)使

            程序調(diào)試更為方便;(2)支持資源的按需獲取。
            6、AddRef&Release的例子
            ULONG _stdcall AddRef()
            {
            ??? return InterlockedIncrement(&m_cRef);
            }
            ULONG _stdcall Release()
            {
            ??? if(InterlockedDecrement(&m_cRef)
            ??? {
            ??????? delete this;
            ??????? return 0;
            ??? }
            ??? return m_cRef;
            }
            7、當(dāng)建立一個新組件時,應(yīng)建立一個對此組件的引用。因此創(chuàng)建組件時,在將指針返回給客戶

            之前,應(yīng)該增大組件的引用計數(shù)值。這使程序員可以不必在調(diào)用CreateInstance 或

            QueryInterface之后記著去調(diào)用AddRef。
            8、引用計數(shù)規(guī)則優(yōu)化:
            (1)輸出參數(shù)規(guī)則:任何在輸出參數(shù)中或作誒返回值返回一個新的接口指針的函數(shù)必須對此接

            口指針調(diào)用AddRef。
            (2)輸入?yún)?shù)規(guī)則:對傳入函數(shù)的接口指針,無需調(diào)用AddRef和Release,這是因為函數(shù)的生命

            期嵌套在調(diào)用者的生命周期內(nèi)。
            (3)輸入-輸出函數(shù)規(guī)則:對于用輸入-輸出參數(shù)傳遞進(jìn)來的接口指針,必須在給它賦另外一個

            接口指針之前調(diào)用其Release。在函數(shù)返回之前,還必須對輸出參數(shù)中所保存的接口指針調(diào)用

            AddRef。如:
            void ExchangeForCachedPtr( int i, IX **ppIX)
            {
            ??? (*ppIX)->Fx();? //Do something with in-parameter.
            ??? (*ppIX)->Release();//Release in parameter.
            ??? *ppIX = g_Cache[i];//Get cached pointer.
            ??? (*ppIX)->AddRef();//AddRef pointer.
            ??? (*ppIX)->Fx();//Do something with out-parameter.
            }
            (4)局部變量規(guī)則:對于局部復(fù)制的接口指針,由于它們只是在函數(shù)的生命周期內(nèi)才存在,因

            此無需調(diào)用AddRef和Release。
            (5)全局變量規(guī)則:對于保存在全局變量中的接口指針,在將其傳遞給另外一個函數(shù)之前,必

            須調(diào)用其AddRef。由于此變量是全局的,因此任何函數(shù)都可以通過調(diào)用其Release來終止其生命

            期。對于保存在成員變量中的接口指針,也應(yīng)按此種方式進(jìn)行處理。因為類中的任何成員函數(shù)都

            可以改變次中接口指針的狀態(tài)。
            (6)不能確定時的規(guī)則:對于任何不能確定的情形,都應(yīng)調(diào)用AddRef和Release對。
            ?
            ////////////////////////////////////////////////////////////////////

            第5章 動態(tài)鏈接

            1、從DLL中輸出函數(shù):用extern "c"標(biāo)記。
            2、在使用VC時,可以用DUMPBIN。EXE來得到某個DLL中所輸出的符號的清單。如下面的命令:

            dumpbin -exports Cmpnt1.dll
            3、裝載DLL:LoadLibrary以被裝載的DLL的名稱作為參數(shù)并返回一個指向所裝載的DLL的句柄。

            win32的GetProcAddress函數(shù)可以使用此句柄以及待用的函數(shù)的名稱,然后返回一個指向次函數(shù)

            的指針。
            4、使用DLL實現(xiàn)組件的原因:DLL可以共享它們所鏈入的應(yīng)用程序的地址空間。

            //////////////////////////////////////////////////////////////////////

            第6章 關(guān)于HRESULT、GUID、注冊表及其他細(xì)節(jié)

            1、HRESULT值的結(jié)構(gòu):
            ?_________________________________________________________
            |????|??????????????????????????????????????????????????|????????????????????? ??????????????????????????????????????|???????????????????????????????????????????
            |?? ?|?????????????15bits設(shè)備代碼? ????????? |?????? 16bits返回代碼?????????????? ??? ???????? |
            |__|_________________________|______________________________|
            ?31 30?????????????????????????????????????????16??15?????????????????????????? 0???????????????????????


            2、常用的HRESULT值:
            3、一般不能直接將HRESULT值同某個成功代碼(如S_OK)進(jìn)行比較以決定某個函數(shù)是否成功也不

            能直接將其同某個失敗代碼(如E_FAIL)進(jìn)行比較以決定函數(shù)調(diào)用是否失敗。應(yīng)該使用

            SECCEEDED和FAILED宏。
            HRESULT hr = CoCreateInstance(...);
            if(FAILED(hr))
            ??? return ;
            hr = pI->QueryInterface(...);
            if(SUCCEEDED(hr))
            {
            ??? pIX->Fx();
            ??? pIX->Release();
            }
            pI->Release();

            4、當(dāng)前所定義的設(shè)備代碼:
            ——————————————————————————————————
            FACILITY_WINDOWS??8
            FACILITY_STORAGE??3
            FACILITY_SSPI???9
            FACILITY_RPC???1
            FACILITY_WIN32???7
            FACILITY_CONTROL??10
            FACILITY_NULL???0
            FACILITY_ITF???4
            FACILITY_DISPATCH??2
            FACILITY_CERT???11
            ——————————————————————————————————

            5、關(guān)于定義自己的HRESULT的一些一般性規(guī)則:
            (1)不要將0X0000及IX01FF范圍內(nèi)的值作為返回代碼。這些值是為COM所定義的FACILITY_ITF代

            碼而保留的。只有遵循這一規(guī)則,才不致使用戶自己定義的代碼同COM所定義的代碼相混淆。
            (2)不要傳播FACILITY_ITF錯誤代碼。
            (3)盡可能使用通用的COM成功及失敗代碼。
            (4)避免定義自己的HRESULT,而可以在函數(shù)中使用一個輸出參數(shù)。
            6、用MAKE_HRESULT宏來定義一個HRESULT值,此宏可根據(jù)所提供的嚴(yán)重級別、設(shè)備代碼及返回代

            碼生成一個HRESULT值。如:
            MAKE_HRESULT(SEVERITY_ERROR,F(xiàn)ACILITY_ITF,100);
            7、GUID是英文Globally Unique Identifier(全局唯一標(biāo)識符)的首字母縮寫。IID是一個128比

            特(16)字節(jié)的一個GUID結(jié)構(gòu)。
            8、生成GUID :UUIDGEN.EXE和GUIDGEN.EXE
            9、GUID的比較:操作符==;等價函數(shù)IsEqualGUID,IsEqualIID,IsEqualCLSID。
            10、將GUID作為組件標(biāo)識符
            11、由于一個GUID值占用了16個字節(jié),因此一般不用值傳遞GUID參數(shù)。而大量使用的是按引用傳

            遞。
            12、COM只使用了注冊表的一個分支:HKEY_CLASSES_ROOT。
            13、注冊表CLSID是一個具有如下格式的串:
            {********-****-****-****-************}
            14、CLSID關(guān)鍵字的子關(guān)鍵字InprocServer32關(guān)鍵字的缺省值是組件所在的DLL文件名稱。
            15、一些特殊關(guān)鍵字:
            (1)AppID:此關(guān)鍵字下的子關(guān)鍵字的作用是將某個APPID(應(yīng)用程序ID)隱射成某個遠(yuǎn)程服務(wù)

            器名稱。分布式COM將用到此關(guān)鍵字。
            (2)組見類別:注冊表的這一分支可以將CATID(組件類別ID)映射成某個特定的組件類別。
            (3)Interface:用于將IID映射成與某個接口相關(guān)的信息。
            (4)Licenses:保存授權(quán)使用COM組件的一些許可信息。
            (5)TypeLib:類型庫關(guān)鍵字所保存的是關(guān)于接口成員函數(shù)所用參數(shù)的信息等。
            16、ProgID命名約定:
            <Program>.<component>.<version>
            17、從ProgID到CLSID的轉(zhuǎn)換:COM庫函數(shù):CLSIDFromProgID和ProgIdFromCLSID:
            CLSID clsid;
            CLSIDFromProgID("****.****.****",&clsid);
            18、自注冊:DLL一定要輸出下邊兩個函數(shù):
            STDAPI DllRegisterServer();
            STDAPI DllUnregisterServer();
            用戶可以使用程序REGSVR32.EXE來注冊某個組件,它實際上是通過上述函數(shù)來完成組件的注冊的


            19、組件類別使開發(fā)人員能夠使開發(fā)人員無需創(chuàng)建組件實例就能決定它是否特工所需接口。一個

            組件類別實際上就是一個接口集合,該集合將被分配給一個GUID,此GUID此時被稱做是CATID。

            對于某個組件而言,若它實現(xiàn)了某個組件類別的所有接口,那么它可以將其注冊成該組件類別的

            一個成員。這樣,客戶就能夠通過從注冊表中選擇只屬于某個特定組件類別的組件而準(zhǔn)確找到它

            所需的組件。
            20、組件類別的用途:指定某個組件必須實現(xiàn)的接口集合;用于指定組件需要其客戶提供的接口

            集合。
            22、在使用COM庫中的其他函數(shù)(除CoBuildVersion外,此函數(shù)將返回COM庫的版本號)之前,進(jìn)

            程必須先調(diào)用CoInitialize來初始化COM庫函數(shù)。當(dāng)進(jìn)程不再需要使用COM庫函數(shù)時,必須調(diào)用

            CoUninitialize。對每一個進(jìn)程,COM庫函數(shù)只需初始化一次。這并不是說不能多次調(diào)用

            CoInitailize,但需保證每一個CoInitialize都有一個相應(yīng)的CoUnoinitialize調(diào)用。當(dāng)進(jìn)程已

            經(jīng)調(diào)用過CoInitialize后,再次調(diào)用此函數(shù)所得到的返回值將是S_FALSE而不再是S_OK.
            23、OLE是建立在COM基礎(chǔ)之上的,它增加了對類型庫、剪貼板、拖放、ActiveX文檔、自動化以

            及ActiveX控件的支持。在OLE庫中包含對這些特性的額外的支持。在需要使用這些特性時,應(yīng)調(diào)

            用OleInitailize及OleUninitialize,而不是CoInitailize和 CoUninitialize。Ole*函數(shù)將調(diào)用

            Co*函數(shù)。但若程序中沒有用到那些額外的功能,使用Ole*將會造成資源的浪費。
            24、COM中分配和釋放內(nèi)存的標(biāo)準(zhǔn)方法:任務(wù)內(nèi)存分配器。使用此分配器,組件可以給客戶提供

            一塊可以由客戶刪除的內(nèi)存。可在多線程應(yīng)用程序中使用。
            一些方便的函數(shù):
            void? *CoTaskMemAlloc(
            ULONG cb? //size in bytes of block to be allocated
            );
            void CoTaskMemFree(
            void *pv? //pointer to memory block to be freed
            );
            25、StringFromGUID2可以將某個GUID轉(zhuǎn)換成一個字符串:
            wchar_t szCLSID[39];
            int r = ::StringFromGUID2(CLSID_Component1,szCLSID,39);
            ?傳給StringFromGUID2的參數(shù)是一個Unicode串(即一個寬字符wchar_t類型的數(shù)組而不是char類

            型的字符數(shù)組)。在非Unicode的系統(tǒng)中,需要將結(jié)果轉(zhuǎn)化為單字節(jié)字符(char)。為此,可以使

            用ANSI的wcstombs函數(shù)如下:
            #ifndef _UNICODE
            char szCLSID_single[39];
            wcstombs(szCLSID_single,szCLSID,39);
            #end if
            26、
            ----------------------------------------------------------------------------
            函數(shù)????????????????? 用途
            -----------------------------------------------------------------------------
            StringFromCLSID?????? 將CLSID轉(zhuǎn)化成文本串
            -----------------------------------------------------------------------------
            StringFromIID???????? 將IID轉(zhuǎn)化成文本串
            ------------------------------------------------------------------------------
            StringFromGUID2?????? 將GUID轉(zhuǎn)化成文本串。此串將被存放在調(diào)用者所分配的緩沖區(qū)中
            ------------------------------------------------------------------------------
            CLSIDFromString?????? 將一個文本串轉(zhuǎn)化成CLSID
            ------------------------------------------------------------------------------
            IIDFromString???????? 將一個文本串轉(zhuǎn)化成IID
            ------------------------------------------------------------------------------

            posted on 2007-03-22 15:41 jay 閱讀(649) 評論(0)  編輯 收藏 引用 所屬分類: COM

            只有注冊用戶登錄后才能發(fā)表評論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


            伊人久久精品无码av一区| 久久天天躁狠狠躁夜夜2020一| 久久99久国产麻精品66| 国产无套内射久久久国产| A级毛片无码久久精品免费| 亚洲AV无码久久精品蜜桃| 国产精品久久久福利| 久久精品无码一区二区日韩AV| 久久综合日本熟妇| 国内精品综合久久久40p| 亚洲精品午夜国产va久久| 欧美丰满熟妇BBB久久久| 97久久精品人人做人人爽| 亚洲精品乱码久久久久久不卡| 少妇高潮惨叫久久久久久| 亚洲熟妇无码另类久久久| 久久AV高潮AV无码AV| 国产精品岛国久久久久| 日韩亚洲欧美久久久www综合网 | 国产精品久久久久影视不卡| 久久久久亚洲av无码专区导航| 久久国产精品一区| 伊人久久五月天| 人妻少妇久久中文字幕| 亚洲国产精品久久久久婷婷软件 | 久久久久九九精品影院| 欧美伊人久久大香线蕉综合| 青青青青久久精品国产| 欧美亚洲另类久久综合婷婷 | 久久最新免费视频| 久久久www免费人成精品| 国内精品久久久久影院优| 四虎国产精品成人免费久久 | 国产精品岛国久久久久| 无夜精品久久久久久| 97久久久精品综合88久久| 久久一区二区三区99| 久久99精品国产麻豆 | 久久综合亚洲色HEZYO社区| 国产精品久久久亚洲| 久久久久99这里有精品10|