【vc++精品源码栏目提醒】:网学会员,鉴于大家对vc++精品源码十分关注,论文会员在此为大家搜集整理了“【精品】COM 组件设计与应用(11)—IDispatch 及双接口的调用 - 其它资料”一文,供大家参考学习!
COM 组 件 设 计 与 应 用 ( 十 一 ) IDispatch 及 双 接 口 的 调 用 作者:杨老师下载源代码一、前言 前段时间,由于工作比较忙,没有能及时地写作。
其间收到了很多网友的来信询问和鼓励,在此 一 并 表 示 感 谢 。
咳 ......我 也 需 要 工 作 来 养 家 糊 口 呀 ...... 上 回 书 介 绍 了 两 种 方 法 来 写 自 动 化 IDispatch接 口 的 组 件 程 序 ,一 是 用 MFC 方 式 编 写“ 纯 粹 ”的 IDispatch 接 口 ; 二 是 用 ATL 方 式 编 写 “ 双 接 口 ” 的 组 件 。
二 、 IDispatch 接 口 和 双 接 口 使 用 者 要 想 调 用 普 通 的 COM 组 件 功 能 , 必 须 要 加 载 这 个 组 件 的 类 型 库 Type library文 件tlb比 如 在 VC 中 使 用 import。
然 而 , 在 脚 本 程 序 中 , 由 于 脚 本 是 被 解 释 执 行 的 , 所 以 无 法 使用 加 载 类 型 库 的 方 式 进 行 预 编 译 。
那 么 脚 本 解 释 器 如 何 使 用 COM 组 件 那 ? 这 就 是 自 动 化IDispatch组 件 大 显 身 手 的 地 方 了 。
IDispatch 接 口 需 要 实 现 4 个 函 数 , 用 者 只 通 过 这 4 个 函 数 , 调就能实现调用自动化组件中所有的函数。
这 4 个函数功能如下: 组件中提供几个类型库?当然一般都是一个啦。
HRESULT GetTypeInfoCount 但 如 果 你 在 一 个 组 件 中 实 现 了 多 个 IDispatch 接 口 ,那 out UINT pctinfo 就 不 一 定 啦 ( 注 1) 调用者通过该函数取得他想要的类型库。
HRESULT GetTypeInfo 幸 好 , 在 99 的 情 况 下 , 我 们 都 不 用 关 心 这 两 个 函 数 in UINT iTInfo 的 实 现 , 因 为 MFC/ATL 都 帮 我 们 完 成 了 默 认 的 一 个 实 in LCID lcid 现,如果是自己完成函数代码,甚至可以直接返回 out ITypeInfo ppTInfo E_NOTIMPL 表 示 没 有 实 现 。
( 注 2)HRESULT GetIDsOfNames in REFIID riid insize_iscNames LPOLESTR 根 据 函 数 名 称 取 得 函 数 序 号 , 调 用 Invoke 做 准 备 。
为rgszNames 所 谓 函 数 序 号 , 大 家 去 观 察 双 接 口 IDL 文 件 和 MFC in UINT cNames 的 ODL 文 件 ,每 一 个 函 数 和 属 性 都 会 有 id序 号 .... in LCID lcid 这样的描述。
outsize_iscNames DISPID rgDispIdHRESULT Invoke 根据序号,执行函数。
in DISPID dispIdMember 使 用 MFC/ATL 写 的 组 件 程 序 , 我 们 也 不 必 关 心 这 个 函 in REFIID riid 数 的 实 现 。
如 果 是 自 己 写 代 码 ,则 该 函 数 类 似 如 下 实 现 : in LCID lcid switchdispIdMember in WORD wFlags inout DISPPARAMS pDispParams case 1: ..... break out VARIANT pVarResult case 2: ..... break out EXCEPINFO pExcepInfo .... out UINT puArgErr 其 实 , 就 是 根 据 序 号 进 行 分 支 调 用 啦 。
注 3 从 Invoke 函 数 的 实 现 就 可 以 看 出 , 使 用 IDispatch 接 口 的 程 序 , 其 执 行 效 率 是 比 较 低 的 。
ATL 从 效 率 出 发 ,实 现 了 一 种 叫“ 双 接 口 dual”的 接 口 模 式 。
下 面 我 们 来 看 看 ,到 底 什 么 是 双 接口:图 一 、 双 接 口 dual 结 构 示 意 图 从 上 图 中 可 以 看 出 , 所 谓 双 接 口 , 其 实 是 在 一 个 VTAB 的 虚 函 数 表 中 容 纳 了 三 个 接 口 ( 因 为任 何 接 口 都 是 从 IUnknown 派 生 的 , 所 以 就 不 强 调 IUnknown 了 , 叫 做 双 接 口 ) 。
我 们 如 果 从任 意 一 个 接 口 中 调 用 QueryInterface得 到 另 外 的 接 口 指 针 的 话 , 其 实 , 得 到 的 指 针 地 址 都 是 同一 个 。
双 接 口 有 什 么 好 处 那 ? 答 : 好 呀 , 多 好 呀 , 特 别 好 呀 ...... 使用方式 因为 所以脚本语言使用组件 解 释 器 只 认 识 IDispatch 接 口 可以调用,但执行效率最低编 译 型 语 言 使 用 组 件 它 认