vs中調用Com組件的五種方法詳解


轉載自:http://www.cppblog.com/woaidongmao/archive/2011/01/10/138250.html

需求:
1.創建myCom.dll,該COM只有一個組件,兩個接口:
   IGetRes--方法Hello(),
   IGetResEx--方法HelloEx()

2.在工程中導入組件或類型庫

clip_image001 #import "組件所在目錄myCom.dll" no_namespace

clip_image001   #import "類型庫所在目錄myCom.tlb"
clip_image001   using namespace MYCOM;

方法一:

1    CoInitialize(NULL);
2    CLSID clsid;
3    CLSIDFromProgID(OLESTR("myCom.GetRes"),&clsid);
4    CComPtr<IGetRes> pGetRes;//智能指針
5    pGetRes.CoCreateInstance(clsid);
6    pGetRes->Hello();
7    pGetRes.Release();//小心哦!!請看最后的“注意”
8    CoUninitialize();


方法二:

 

1    CoInitialize(NULL);
2    CLSID clsid;
3    HRESULT hr=CLSIDFromProgID(OLESTR("myCom.GetRes"),&clsid);
4    IGetRes *ptr;
5    hr=CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER,
6                  __uuidof(IGetRes),(LPVOID*)&ptr);
7    ptr->Hello();
8    clip_image001   CoUninitialize();

 

方法三:

 

 

 1    CoInitialize(NULL);
 2    HRESULT hr;
 3    CLSID clsid;
 4    hr=CLSIDFromProgID(OLESTR("myCom.GetRes"),&clsid);
 5    IGetRes* ptr;
 6    IGetResEx* ptrEx;
 7    //使用CoCreateClassObject創建一個組件(特別是mutilThreads)的多個對象的
 8      時候,效率更高.
 9    IClassFactory* p_classfactory;
10    hr=CoGetClassObject(clsid,CLSCTX_INPROC_SERVER,
11                        NULL,IID_IClassFactory, 
12                        (LPVOID*)&p_classfactory);
13    p_classfactory->CreateInstance(NULL,__uuidof(IGetRes),
14                                           (LPVOID*)&ptr);
15    p_classfactory->CreateInstance(NULL,__uuidof(IGetResEx),
16                                           (LPVOID*)&ptrEx);
17    ptr->Hello();
18    ptrEx->HelloEx();

 

方法四:
直接從dll中得到DllGetClassObject,接着生成類對象及類實例(這方法可以使組件不用在注冊表里注冊,這是最原始的方法,但這樣做沒什么意義,至少失去了COM對用戶的透明性),不推薦使用.

 1 typedef HRESULT (__stdcall * pfnHello)(REFCLSID,REFIID,void**);
 2 pfnHello fnHello= NULL;
 3 HINSTANCE hdllInst = LoadLibrary("組件所在目錄myCom.dll");
 4 fnHello=(pfnHello)GetProcAddress(hdllInst,"DllGetClassObject");
 5 if (fnHello != 0)
 6 {
 7     IClassFactory* pcf = NULL;
 8     HRESULT hr=(fnHello)(CLSID_GetRes,IID_IClassFactory,(void**)&pcf);
 9     if (SUCCEEDED(hr) && (pcf != NULL))
10     {
11         IGetRes* pGetRes = NULL;
12         hr = pcf->CreateInstance(NULL, IID_IFoo, (void**)&pGetRes);
13         if (SUCCEEDED(hr)   && (pFoo != NULL))
14         {
15             pGetRes->Hello();
16             pGetRes->Release();
17         }
18         pcf->Release();
19     }
20 } 
21 FreeLibrary(hdllInst);

 

 方法五:

通過ClassWizard利用類型庫生成包裝類,不過前提是com組件的接口必須是派生自IDispatch,具體方法:
    調出添加類向導(.NET中),選擇類型庫中MFC類,打開,選擇"文件",選擇"myCom.dll"或"myCom.tlb",接下來會出來該myCom中的所有接口,選擇你想生成的接口包裝類后,向導會自動生成相應的.h文件.這樣你就可以在你的MFC中像使用普通類那樣使用組件了.(CreateDispatch("myCom.GetRes") 中的參數就是ProgID通過Clsid在注冊表中可以查詢的到)

 

1 CoInitialize(NULL);
2 CGetRes getRest;
3 if (getRest.CreateDispatch("myCom.GetRes") != 0)
4 {
5     getRest.Hello();
6     getRest.ReleaseDispatch();
7 }
8 CoUninitialize();

 

 

注意:
COM中的智能指針實際上是重載了->的類,目的是為了簡化引用記數,幾不需要程序員顯示的調用AddRef()和Release(),但是為什么我們在Method 1中pGetRes.Release(),問題在與,我們的智能指針pGetRes生命周期的結束是在CoUninitialize()之后,CoInitialize所開的套間在CoUninitialize()后已經被關閉,而pGetRes此時發生析構,導致了程序的崩潰,解決這個問題的另一個方法是

 

1 CoInitialize(NULL);
2 CLSID clsid;
3 CLSIDFromProgID(OLESTR("myCom.GetRes"),&clsid);
4 {
5     CComPtr<IGetRes> pGetRes;//智能指針
6     pGetRes.CoCreateInstance(clsid);
7     pGetRes->Hello();
8 }
9 CoUninitialize();

 

以上就是COM的5中方法,當然具體怎么使用還是在於程序的環境,加以琢磨....

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM