3 DirectX的COM接口

  DirectX程序员手册中的COM接口是建立在一个很基本的COM程序阶段。 每个对象的接口都表示为一个设备,就象IDirectDraw4,IDirectSound 及 IDirectPlay,都直接来自于IUnknown COM接口。 创建这些基本的对象是靠运用专门的动态衔接库(DLL), 除此之外还用CoCreateInstance功能来创建COM对象。

  一般来说,DirectX对象模式为每个设备提供一个主对象。 其他提供服务的对象是从这个主对象派生出来的。例如: DirectDraw对象就是显示适配器。你能使用它创建DirectDrawSurface 对象来表示显存或DirectDrawPalette对象来表示硬件调色板。相同的 DirectSound对象表示声卡,所创建的DirectSoundBuffer对象表示卡上的音源。

  除此之外,主设备对象能表示并决定硬件设备的性能, 象屏幕尺寸及发色数,及声卡是否有波表合成器。

4 C++与COM接口

  对C++程序员,一个COM接口就象一个抽象类。就是, 它定义设置一个信号灯及语法但不启用,并没有实在的数据与接口。 在一个C++抽象类,所有的宏都定义为抽象虚拟,也就是说他们并无实在的代码.

  C++抽象虚拟函数及COM接口都使用一个叫做VTABLE (译者按:VTABLE可能是Virtual Table,表示虚拟表. 云风:VTABLE 即虚拟表, 是一种用 C 去模拟 C++ 的部分特性的方法,可以方便的将 C 和 C++ 的接口统一起来) 的设备。一个VTABLE包含一个接口所包含的所有函数的地址。 如果你需要一个程序或对象使用这些函数,你可以使用 QueryInterface宏来检验对象上的接口并获得该接口的指针。 在使用QueryInterface后,你的程序或对象事实上就是获得对象VTABLE的指针, 这个宏可以调用对象所包含的接口的宏。 这个机制使另一个或其他对象所使用的私人数据与子进程的调用互不相干。

  COM对象与C++对象的另一个相似之处是宏的第一争用是接口或类的命名, 叫做C++争用。因为COM对象和C++对象在二进制上完全兼容, 编译COM接口与C++抽象类采用的是相同的语法。降低了代码复杂度。 例如:C++争用就象一个已知的参数而不是编码,并由C++间接操作VTABLE。

5 可改动的新接口

  COM可以在不改变已存在的接口宏来增加功能, 只要在新接口中加入新特性。协调接口, 一个基于COM对象可以自由的添加新的服务功能并保持老应用程序的兼容.

  DirectX组件以这为标准。例如:DirectXDraw组件提供三个方法访问一个 DirectDrawSurface:IDirectDrawSurface:IDirectDrawSurface2, IDirectDrawSurface3及IDirectDrawSurface4。 各个版本的接口都提供其老版本的宏,并提供新的宏支持新特性; 如果你的程序不使用这些新特性,就无必要使用新接口。不管怎样, 要使用新接口提供的新特性,你必须调用对象的IUnknown::QueryInterface宏, 来指定你要使用接口的GUID(单一标识符)。接口的GUID在头文件中声明。

  以下例程演示如何查询一个新的接口:

    LPDIRECTDRAW    lpDD1;
    LPDIRECTDRAW2   lpDD2;
 
    ddrval = DirectDrawCreate( NULL, &lpDD1, NULL );
    if( FAILED(ddrval))
        goto ERROROUT;
 
    // 查询IDirectDraw2接口
    ddrval = lpDD1->QueryInterface(IID_IDirectDraw2, (void **)&lpDD2);
    if( FAILED(ddrval))
        goto ERROROUT;
    
    // 现在我们已经拥有IDirectDraw2, 释放原来的接口
    lpDD1->Release();

  在一些特殊情况下,一个新的接口会撤消老版本接口所提供的宏。 IDirect3DDevice2就是这类接口的一个例子。 如果你的程序要使用以前接口提供的特性,你也可以象例程那样查询该接口, 使用老接口的GUID来执行。

6 用C访问构件对象模型

  部分COM接口宏也能从C程序中来调用。但从C中调用接口宏要记住两件事:

7 宏的命名及语法

  所有在这个文档描述的接口宏都用C++类命名。 这命名协议具有一致性并区分不同的却有相同命名DirectX对象宏, 象QueryInterface,AddRef及Release。不过这并不意味着你只能用C++调用这些宏。

  还有,C++调用宏在语法上也有一致性。这并不包括该接口的指针。 在C中,接口指针必须包含在每个宏之中。 以下例子演示使用C++语法的IDirectDraw4::GetCaps宏:

  HRESULT GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps);

同样的在C中应是:

  HRESULT GetCaps(LPDIRECTDRAW4 lpDD, LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps);

lpDD参数是一个指向DirectDraw接口的描述DirectDraw对象的指针。


上篇|返回|下篇

Lucker 1998.12.12
E-Mail: fred_cai@kali.com.cn


云风工作室 制作