使用 C 实现对象

适用于:Outlook 2013 | Outlook 2016

使用 C 编写的客户端应用程序和服务提供程序通过创建数据结构和有序函数指针数组(称为虚拟函数表或 vtable)来定义 MAPI 对象。 指向 vtable 的指针必须是数据结构的第一个成员。

在 vtable 本身中,对象支持的每个接口中的每个方法都有一个指针。 指针的顺序必须遵循 Mapidefs.h 头文件中发布的接口规范中方法的顺序。 vtable 中的每个函数指针都设置为 方法的实际实现的地址。 在 C++ 中,编译器会自动设置 vtable。 在 C 中,它不是。

下图显示了其工作原理。 最左侧的框表示需要使用服务提供程序对象的客户端。 通过会话,客户端获取指向对象 lpObject 的指针。 vtable 首先显示在 对象中,后跟私有数据和方法。 vtable 指针指向实际的 vtable,其中包含指向接口中方法的每个实现的指针。

对象实现

对象实现

下面的代码示例演示 C 服务提供程序如何定义简单的状态对象。 第一个成员是 vtable 指针;对象的其余部分由数据成员组成。

typedef struct _MYSTATUSOBJECT
{
    const STATUS_Vtbl FAR *lpVtbl;
    ULONG              cRef;
    ANOTHEROBJ        *pObj;
    LPMAPIPROP         lpProp;
    LPFREEBUFFER       lpFreeBuf;
} MYSTATUSOBJECT, *LPMYSTATUSOBJ;
 

由于此对象是状态对象,因此 vtable 包括指向 IMAPIStatus 中每个方法实现的指针:IMAPIProp 接口,以及指向基接口中每个方法实现的指针 - IUnknownIMAPIProp。 vtable 中方法的顺序与 Mapidefs.h 头文件中定义的指定顺序匹配。

static const MYOBJECT_Vtbl vtblSTATUS =
{
    STATUS_QueryInterface,
    STATUS_AddRef,
    STATUS_Release,
    STATUS_GetLastError,
    STATUS_SaveChanges,
    STATUS_GetProps,
    STATUS_GetPropList,
    STATUS_OpenProperty,
    STATUS_SetProps,
    STATUS_DeleteProps,
    STATUS_CopyTo,
    STATUS_CopyProps,
    STATUS_GetNamesFromIDs,
    STATUS_GetIDsFromNames,
    STATUS_ValidateState,
    STATUS_SettingsDialog,
    STATUS_ChangePassword,
    STATUS_FlushQueues
};
 

以 C 编写的客户端和服务提供商通过 vtable 间接使用对象,并在每次调用中添加对象指针作为第一个参数。 每次调用 MAPI 接口方法都需要指向作为其第一个参数调用的对象的指针。 为此,C++ 定义了一个称为 指针的特殊指针。 C++ 编译器 将此指针隐 式添加为每个方法调用的第一个参数。 在 C 中没有此类指针;必须显式添加它。

以下代码演示客户端如何调用 MYSTATUSOBJECT 实例:

lpMyObj->lpVtbl->ValidateState(lpMyObj, ulUIParam, ulFlags);
 

另请参阅