VC中COM调用的方法

来源:岁月联盟 编辑:exp 时间:2012-10-19

近刚开始学习COM编程,里面诸多的知识让我有点吃不消,将学习的点滴进行记录,跟大家分享。对于com的调用一直没怎么搞明白,今天通过查资料将其进行整理。(这里为了方便,dll的开发主要参考杨老师的这篇COM 组件设计与应用(五)——用 ATL 写第一个组件)。

      COM的调用方法主要有一下几种:

准备工作
DLL函数调用
COM组件功能调用
   一、准备工作

1.创建simple.dll,该COM只有一个组件,组件的ProgID为"Simple.Fun.1",一个接口:
[cpp] 
IFun--方法Add(), 
IFun--方法Cat() 
2.在工程中导入组件或类型库
[cpp] view plaincopy
#import "组件所在目录simple.dll" no_namespace 
 
  #import "类型库所在目录simple.tlb"  using namespace MYCOM; 
   二、DLL函数调用
     通过获取函数地址进行调用DLL。通过GetProcAddress直接获取方法,接着生成类对象及类实例(这方法可以使组件不用在注册表里注册,这是最原始的方法,但这样做没什么意义,至少失去了COM对用户的透明性),不推荐使用.
[cpp] 
//  加载动态库  
hModule = LoadLibrary(TEXT(" simple.dll")); 
if(hModule) 

    //  获取函数地址  
    fnAdd = (LPFunc)GetProcAddress(hModule, TEXT("Add")); 
    if(fnAdd) 
    { 
        //  调用函数  
        iRet = fnAdd( 2 ,  4 ); 
        printf( " Result is %d " , iRet); 
    }  
    //  释放动态库  
    FreeLibrary(hModule); 
    hModule  =  NULL; 

    三、COM组件功能调用
 1.使用COM的智能指针。
[cpp]
CoInitialize(NULL); 
CLSID clsid; 
HRESULT hr=CLSIDFromProgID(OLESTR("Simple.Fun.1"),&clsid); 
CComPtr<IFun> pIFun;//智能指针 
pIFun.CoCreateInstance(clsid); 
long ret = pIFun->Add(12,12); 
TCHAR buf[1024]; 
wsprintf(buf,TEXT("the retValue is: %d/n"),ret); 
MessageBox(NULL, buf, TEXT("RESULT"),MB_OK); 
pIFun.Release();//注意下 
CoUninitialize(); 
      COM中的智能指针实际上是重载了->的类,目的是为了简化引用记数,几不需要程序员显示的调用AddRef()和Release(),但是为什么我们在Method 1中pGetRes.Release(),问题在与,我们的智能指针pGetRes生命周期的结束是在CoUninitialize()之后,CoInitialize所开的套间在CoUninitialize()后已经被关闭,而pGetRes此时发生析构,导致了程序的崩溃,解决这个问题的另一个方法是:
[cpp] 
CoInitialize(NULL); 
CLSID clsid; 
CLSIDFromProgID(OLESTR("Simple.Fun.1"),&clsid); 

    CComPtr<IFun> pIFun;//智能指针 
    pIFun.CoCreateInstance(clsid); 
    long ret = pIFun->Add(12,12); 
    TCHAR buf[1024]; 
    wsprintf(buf,TEXT("the retValue is: %d/n"),ret); 
    MessageBox(NULL, buf, TEXT("RESULT"),MB_OK); 

CoUninitialize(); 
2.这中方式通过定义接口指针进行操作。
[cpp]
CoInitialize(NULL); 
CLSID clsid; 
HRESULT hr=CLSIDFromProgID(OLESTR("Simple.Fun.1"),&clsid); 
IFun *ptr; 
hr=CoCreateInstance(clsid,NULL,CLSCTX_INPROC_SERVER, 
    __uuidof(IFun),(LPVOID*)&ptr); 
long ret = ptr->Add(12,12); 
TCHAR buf[1024]; 
wsprintf(buf,TEXT("the retValue is: %d/n"),ret); 
MessageBox(NULL, buf, TEXT("RESULT"),MB_OK); 
CoUninitialize(); 

    所谓的插件技术不过是在主程序上指定一套接口,所有遵循接口的可加载模块都是插件。主程序可以采用上面的方法去加载任意的dll,调用方法功能,只要满足就是插件,这样插件体系不再局限于COM接口级别,一个插件可以采用以上形式去实现。