龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > VC开发 >

COM技术纵横谈(3)

时间:2009-12-30 15:42来源:未知 作者:admin 点击:
分享到:
上例中,定义了IA,IB两个接口,你可以注意到他们所有的成员函数都被声明为virtual,并且在函数末尾用 = 0 做了结束。类似这样的函数我们在C++中称之为
  上例中,定义了IA,IB两个接口,你可以注意到他们所有的成员函数都被声明为virtual,并且在函数末尾用 = 0 做了结束。类似这样的函数我们在C++中称之为纯虚函数,如果整个的类都由纯虚函数组成,那么这个类就叫做抽象基类。抽象基类本身由于没有实体函数与变量,所以并不分配内存。一般它的用途是为派生类指定内存结构。打个比方来说,就好像把房子分割成很多小间,规定以后哪些小间应该放什么(函数的实体)但具体的东西则要等派生类来填放。

  这里有一个概念需要说明一下:组件并不是类,上面我们用一个类就实现了两组接口,同样我们也可以用它来实现更多接口。组件本身其实只是一个接口集及其实现的集合。一个组件可能包含了多个接口,每一个接口都有各自的实现。同时,接口并非总是继承的,COM规范没有要求实现某个接口的类必须从那个接口继承。这是因为客户并不了解COM组件的继承关系。对接口的继承只不过是一种实现细节而已。

  下面将介绍QueryInterface函数。这个函数被用来查询其他接口。客户于组件之间的通讯是通过接口完成的。哪怕是客户查询其他一个组件时,也需要通过一个接口(换而言之,如果一个组件不支持这个接口,那他一定不是一个COM组件)这个接口的名字叫IUnknown,它有三个函数,如下所示:

interface IUnknown
{
    virtual HRESULT __stdcall QueryInterface(const IID& iid, void** ppv) = 0;
    virtual ULONG __stdcall AddRef() = 0;
    virtual ULONG __stdcall Release() = 0;
}; 


  COM组件的所有接口都继承了IUnknown,这样一来,每一个接口的前三个函数都是QueryInterface,这就是的所有的COM接口都可以被当成是IUnknown来处理。客户只要通过一个CoCreateInstance函数就可以创建该组件的实例并且获取其IUnknown*。

HRESULT __stdcall CoCreateInstance(
            const CLSID& clsid,
            IUnknown* pIUnknownOuter,
            DWORD dwClsContext,
            const IID& iid,
            void** ppv
         );
下面的CODE演示创建一个组件:

extern "C" const GUID CLSID_COM1 = (
        0x32bb8230, 0xb41b1 0x11cf, 0xa6, 0xbb, 0x0, 0x80, 0xc7, 0xb2, 0xd6, 0x82 );

extern "C" const GUID IID_IX = (
        0x32bb8230, 0xb591c 0x11ff, 0xc1, 0xb0, 0xc7, 0xf8, 0x21, 0x35, 0x1c, 0x2f );

CoInitialize();

Ia* pIx = NULL;
HRESULT hr = ::CoCreateInstance(
                CLSID_COM1,
                NULL,
                CLSCTX_INPROC_SERVER,
                IID_IX,
                (void**) &pIx
            );

if (SUCCEEDED(hr))
{
    pIx -> Fx();
    pIx -> Release();

 
  extern "C" const GUID其实是所谓的"全局唯一标示符"(Globally Unique Identifier)。我们规定用它来表示不同的接口。换而言之,如果你发现有两个GUID完全相同,你完全有理由相信他们标示的是同一个接口。(有专门的算法来产生该结构,确保它在时间和空间上都是唯一的。) 接下来的CoInitialize函数初始化COM库。这一步是非常重要的,如果没有初始化,以后进行的操作都将失败。

精彩图集

赞助商链接