国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

用純粹的C++編寫COM組件

2019-11-17 05:30:14
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
下載本文代碼     本文提供一個(gè)完全用C++實(shí)現(xiàn)的進(jìn)程內(nèi)(DLL)COM服務(wù)器,不要ATL或MFC提供任何支持。用這種方式編寫COM對(duì)象可以讓你深入地洞察到COM處理進(jìn)程內(nèi)服務(wù)器的方法以及COM是如何創(chuàng)建類工廠的。利用本文提供的這個(gè)簡(jiǎn)單框架你可以實(shí)現(xiàn)很基本的COM組件,如外殼擴(kuò)展(Shell Extensions)等。假如你在使用過(guò)程中發(fā)現(xiàn)了任何問題,請(qǐng)將它反饋到vckbase@public.hk.hi.cn。

以下是用本文所說(shuō)的方式編寫自己的COM對(duì)象要經(jīng)過(guò)的步驟:

第一步:寫一個(gè)頭文件,這個(gè)頭文件包含以下內(nèi)容:
1、 包含文件comdef.h:#include
2、 定義COM服務(wù)器的GUID。_declspec(selectany) GUID CLSID_Mine = { 0xdc186800, 0x657f, 0x11d4, {0xb0, 0xb5, 0x0, 0x50, 0xba, 0xbf, 0xc9, 0x4} };3、 給出接口的IID以及這個(gè)接口要實(shí)現(xiàn)的方法定義。到時(shí)客戶端會(huì)用到這個(gè)接口的IID和接口的方法。interface __declspec(uuid("F614FB00-6702-11d4-B0B7-0050BABFC904")) ImyInterface : public IUnknown{ STDMETHOD(Square)(long *pVal)PURE; STDMETHOD(Cube)(long *pVal)PURE;};客戶端使用此接口:HRESULT hr;ImyInterface *pmine=(0);hr = CoCreateInstance(CLSID_Mine, // COM 服務(wù)器的CLSID NULL, //不支持聚合 CLSCTX_INPROC_SERVER, // 是個(gè)DLL __uuidof(ImyInterface), // 接口的IID (void**)&pmine );還有一種方法可以從注冊(cè)表中獲得COM對(duì)象的CLSID,就是調(diào)用CLSIDFromProgId()函數(shù),不過(guò)必須把組件的ProgId傳遞給這個(gè)函數(shù)。

第二步:必須為所定義的接口提供實(shí)現(xiàn),本文用的方法是創(chuàng)建一個(gè)從接口繼續(xù)的新類:

// 這個(gè)類實(shí)現(xiàn)單接口ImyInterface ...
// 
//class CmyInterface : public CComBase<> , public InterfaceImpl {public: CmyInterface(); virtual ~CmyInterface(); // 我們必須要為QueryInterface 編寫代碼 STDMETHOD(QueryInterface)(REFIID riid,LPVOID *ppv); // ImyInterface 接口方法 STDMETHOD(Square)(long *pVal); STDMETHOD(Cube)(long *pVal);};模版類InterfaceImpl<>提供接口引用計(jì)數(shù)的實(shí)現(xiàn)。在此我們可以用多接口繼續(xù),那樣就能在一個(gè)COM組件中實(shí)現(xiàn)多個(gè)接口。

第三步:在完成這個(gè)對(duì)象之前,我們還要編寫Queryinterface和兩個(gè)接口方法:STDMETHODIMP CmyInterface::QueryInterface(REFIID riid,LPVOID *ppv){ *ppv = NULL; if(IsEqualIID(riid,IID_IUnknown) IsEqualIID(riid,__uuidof(ImyInterface))) { // 因?yàn)槲覀儚腎myInterface繼續(xù),所以要進(jìn)行強(qiáng)制類型轉(zhuǎn)換 *ppv = (ImyInterface *) this; _AddRef(); // 這個(gè)方法從某個(gè)基類繼續(xù)而來(lái) return S_OK; } return E_NOINTERFACE;}STDMETHODIMP CmyInterface::Square(long *pVal){ long value = *pVal; *pVal = value * value; return S_OK;}STDMETHODIMP CmyInterface::Cube(long *pVal){ long value = *pVal; *pVal = value * value * value; return S_OK;}    注重這里使用了__uuidof(ImyInterface)來(lái)獲取接口的IID,這是因?yàn)槲覀円呀?jīng)在第一步中將這個(gè)接口關(guān)聯(lián)到了某個(gè)uuid。

最后一步:COM 組件的DLLs必須輸出一個(gè)叫DllGetClassObject的函數(shù)。由這個(gè)函數(shù)為CmyInterface創(chuàng)建類工廠并返回一個(gè)對(duì)它的引用。然后我們調(diào)用CoCreateInstance為進(jìn)程內(nèi)COM創(chuàng)建類工廠,接著調(diào)用DllGetClassObject。這個(gè)類工廠有一個(gè)方法是CreateInstance,由這個(gè)方法創(chuàng)建對(duì)象并返回對(duì)它的引用。STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut){ *ppvOut = NULL; if (IsEqualIID(rclsid, CLSID_Mine)) {
// 為CmyInterface類聲明類工廠 CClassFactory *pcf = new CClassFactory; return pcf->QueryInterface(riid,ppvOut); } return CLASS_E_CLASSNOTAVAILABLE;}    在此我們要檢查所請(qǐng)求的CLSID是不是CLSID_Mine,假如不是則返回一個(gè)錯(cuò)誤代碼。
你可能會(huì)問在哪里創(chuàng)建實(shí)際的CmyInterface類對(duì)象,實(shí)際上這是由CClassFactory模板實(shí)例來(lái)處理的。以下是CClassFatory的實(shí)現(xiàn):

// CSingleCreator 用于單實(shí)例類工廠,這個(gè)類為多個(gè)CreateObject請(qǐng)求返回相同的對(duì)象指針..templateclass CSingleCreator{protected: CSingleCreator():m_pObj(0) {}; comObj *CreateObject() { if(!m_pObj) { m_pObj = new comObj; } return m_pObj; } comObj * m_pObj;};// CMultiCreator 用于常用類工廠,這個(gè)類為每一個(gè)CreateObject請(qǐng)求返回新的對(duì)象指針..templateclass CMultiCreator{protected: CMultiCreator():m_pObj(0) {}; comObj *CreateObject() { return new comObj; } comObj * m_pObj;};//ClassFactory類實(shí)現(xiàn)// MultiCreator是缺省的類工廠創(chuàng)建者//這個(gè)類實(shí)現(xiàn)了接口IclasFactory......class CClassFactory : public CComBase<>, public InterfaceImpl, public creatorClass {public: CClassFactory() {}; virtual ~CClassFactory() {}; STDMETHOD(QueryInterface)(REFIID riid,LPVOID *ppv) { *ppv = NULL; if(IsEqualIID(riid,IID_IUnknown) IsEqualIID(riid,IID_IClassFactory)) { *ppv = (IClassFactory *) this; _AddRef(); return S_OK; } return E_NOINTERFACE; } STDMETHODIMP CreateInstance(LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObj) { *ppvObj = NULL; if (pUnkOuter) return CLASS_E_NOAGGREGATION; m_pObj = CreateObject(); // m_pObj 在creatorClass中定義 if (!m_pObj) return E_OUTOFMEMORY; HRESULT hr = m_pObj->QueryInterface(riid, ppvObj); if(hr != S_OK) { delete m_pObj; } return hr; } STDMETHODIMP LockServer(BOOL) { return S_OK; } // 未實(shí)現(xiàn)};    COM調(diào)用CreateInstance創(chuàng)建請(qǐng)求的對(duì)象,參數(shù)riid指的是所請(qǐng)求的接口IID,假如這個(gè)對(duì)象支持這個(gè)接口,則增加它的引用計(jì)數(shù)并返回對(duì)自身的引用。

    關(guān)于代碼:本文所提出的方法是如何用純粹的C++編寫COM組件的一個(gè)大概念。很多方面的細(xì)節(jié)都省略了。從本文的文字和代碼中可以看出用純C++編寫COM組件需要做些什么工作,假如你要用這種方法編寫COM組件的話,這些代碼只能是拋磚引玉,具體的實(shí)現(xiàn)可以在此基礎(chǔ)上往下做.......。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 涟源市| 平顶山市| 萝北县| 海阳市| 台山市| 册亨县| 敦煌市| 白玉县| 仁怀市| 沭阳县| 澄城县| 田阳县| 嘉善县| 唐山市| 德保县| 延安市| 元阳县| 清水县| 都兰县| 措美县| 木里| 和政县| 蛟河市| 双牌县| 寻乌县| 台南市| 开江县| 丹江口市| 仙游县| 台东市| 温州市| 忻城县| 商洛市| 龙海市| 西平县| 新密市| 台江县| 垣曲县| 宿迁市| 阜城县| 霍山县|