COM编程入门-.pdf
《COM编程入门-.pdf》由会员分享,可在线阅读,更多相关《COM编程入门-.pdf(24页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。
1、1 COM编 程 入 门第 一 部 分 什 么 是 COM,如 何 使 用 COM 本 文 的 目 的 是 为 刚 刚 接 触 COM 的 程 序 员 提 供 编 程 指 南,并 帮 助 他 们 理 解 COM 的 基 本 概 念。内 容 包 括 COM 规 范 简 介,重 要 的 COM 术 语 以 及 如 何 重 用 现 有 的 COM 组 件。本 文 不 包 括 如 何 编写 自 己 的 COM 对 象 和 接 口。COM 即 组 件 对 象 模 型,是 Component Object Model 取 前 三 个 字 母 的 缩 写,这 三 个 字 母 在当 今 W indows的 世
2、 界 中 随 处 可 见。随 时 涌 现 出 来 的 大 把 大 把 的 新 技 术 都 以 COM 为 基 础。各 种文 档 中 也 充 斥 着 诸 如 COM 对 象、接 口、服 务 器 之 类 的 术 语。因 此,对 于 一 个 程 序 员 来 说,不 仅要 掌 握 使 用 COM 的 方 法,而 且 还 要 彻 底 熟 悉 COM 的 所 有 一 切。本 文 由 浅 入 深 描 述 COM 的 内 在 运 行 机 制,教 你 如 何 使 用 第 三 方 提 供 的 COM 对 象(以W indows 外 壳 组 件 Shell 为 例)。读 完 本 文 后,你 就 能 掌 握 如 何
3、使 用 W indows操 作 系 统 中 内 建的 组 件 和 第 三 方 提 供 的 COM 对 象。本 文 假 设 你 精 通 C+语 言。在 例 子 代 码 中 使 用 了 一 点 MFC 和 ATL,如 果 你 不 熟 悉 MFC 和ATL 也 没 关 系,本 文 会 对 这 些 代 码 进 行 完 全 透 彻 的 解 释。本 文 包 括 以 下 几 个 部 分:COM 到 底 是 什 么?CO M 标 准 的 要 点 介 绍,它 被 设 计 用 来 解 决 什 么 问 题基 本 元 素 的 定 义 COM 术 语 以 及 这 些 术 语 的 含 义使 用 和 处 理 COM 对 象
4、 如 何 创 建、使 用 和 销 毁 COM对 象基 本 接 口 描 述 IUnknown 基 本 接 口 及 其 方 法掌 握 串 的 处 理 在 COM 代 码 中 如 何 处 理 串应 用 COM 技 术 例 子 代 码,举 例 说 明 本 文 所 讨 论 的 所 有 概 念处 理 HRES ULT HRES ULT 类 型 描 述,如 何 监 测 错 误 及 成 功 代 码COM 到 底 是 什 么简 单 地 说,COM 是 一 种 跨 应 用 和 语 言 共 享 二 进 制 代 码 的 方 法。与C+不 同,它 提 倡 源 代 码重 用。ATL 便 是 一 个 很 好 的 例 证。源
5、 码 级 重 用 虽 然 好,但 只 能 用 于 C+。它 还 带 来 了 名 字 冲 突的 可 能 性,更 不 用 说 不 断 拷 贝 重 用 代 码 而 导 致 工 程 膨 胀 和 臃 肿。W indows使 用 DLLs 在 二 进 制 级 共 享 代 码。这 也 是 W indows程 序 运 行 的 关 键 重 用kernel32.dll,user32.dll 等。但 DLLs 是 针 对 C 接 口 而 写 的,它 们 只 能 被 C 或 理 解 C 调 用 规 范 的语 言 使 用。由 编 程 语 言 来 负 责 实 现 共 享 代 码,而 不 是 由 DLLs 本 身。这 样
6、的 话 DLLs 的 使 用 受 到限 制。MFC 引 入 了 另 外 一 种 MFC 扩 展 DLLs 二 进 制 共 享 机 制。但 它 的 使 用 仍 受 限 制 只 能 在 MFC 程序 中 使 用。COM 通 过 定 义 二 进 制 标 准 解 决 了 这 些 问 题,即 COM 明 确 指 出 二 进 制 模 块(DLLs 和 EXEs)必 须 被 编 译 成 与 指 定 的 结 构 匹 配。这 个 标 准 也 确 切 规 定 了 在 内 存 中 如 何 组 织 COM 对 象。COM定 义 的 二 进 制 标 准 还 必 须 独 立 于 任 何 编 程 语 言(如 C+中 的 命
7、 名 修 饰)。一 旦 满 足 了 这 些 条 件,就 可 以 轻 松 地 从 任 何 编 程 语 言 中 存 取 这 些 模 块。由 编 译 器 负 责 所 产 生 的 二 进 制 代 码 与 标 准 兼 容。这 样 使 后 来 的 人 就 能 更 容 易 地 使 用 这 些 二 进 制 代 码。在 内 存 中,COM 对 象 的 这 种 标 准 形 式 在 C+虚 函 数 中 偶 尔 用 到,所 以 这 就 是 为 什 么 许 多COM 代 码 使 用 C+的 原 因。但 是 记 住,编 写 模 块 所 用 的 语 言 是 无 关 的,因 为 结 果 二 进 制 代 码 为所 有 语 言
8、可 用。此 外,COM 不 是 W in32特 有 的。从 理 论 上 讲,它 可 以 被 移 植 到 Unix 或 其 它 操 作 系 统。但是 我 好 像 还 从 来 没 有 在 W indows以 外 的 地 方 听 说 过 COM。基 本 元 素 的 定 义我 们 从 下 往 上 看。接 口 只 不 过 是 一 组 函 数。这 些 函 数 被 称 为 方 法。接 口 名 字 以 大 写 的 I 开头,例 如 C+中 的 IShellL ink,接 口 被 设 计 成 一 个 抽 象 基 类,其 中 只 有 纯 粹 的 虚 拟 函 数。接 口 可 以 从 其 它 接 口 继 承,这 里
9、所 说 的 继 承 的 原 理 就 好 像 C+中 的 单 继 承。接 口 是 不 允 许多 继 承 的。2 coclass(简 称 组 件 对 象 类 component object class)被 包 含 在 DLL 或 EXE 中,并 且 包 含 着 一个 或 者 多 个 接 口 的 代 码。组 件 对 象 类(coclasss)实 现 这 些 接 口。COM 对 象 在 内 存 中 表 现 为 组件 对 象 类(coclasss)的 一 个 实 例。注 意 COM“类”和 C+“类”是 不 相 同 的,尽 管 常 常 COM 类 实现 的 就 是 一 个 C+类。/哪 里 不 同?C
10、OM 服 务 器 是 包 含 了 一 个 或 多 个 coclass的 二 进 制(DLL 或 EXE)。注 册(Registration)是 创 建 注 册 表 入 口 的 一 个 过 程,告 诉 W indows 操 作 系 统 COM 服 务 器 放 在什 么 位 置。取 消 注 册(Unregistration)则 相 反 从 注 册 表 删 除 这 些 注 册 入 口。GUID(谐 音 为“flu id”,意 思 是 全 球 唯 一 标 示 符 globally un ique identifier)是 个 128 位 的 数字。它 是 一 种 独 立 于 COM 编 程 语 言 的
11、 标 示 方 法。每 一 个 接 口 和 coclas s 有 一 个 GU ID。因 为 每 一个 GU ID 都 是 全 球 唯 一 的,所 以 避 免 了 名 字 冲 突(只 要 你 用 COM AP I 创 建 它 们)。有 时 你 还 会碰 到 另 一 个 术 语 UU ID(意 思 也 是 全 球 唯 一 标 示 符 univ ersally unique identifier)。UU IDs和 GU IDs 在 实 际 使 用 时 的 用 途 是 一 样 的。类 ID 或 者 CLSID 是 命 名 coclass的 GU ID。接 口 ID 或 者 IID 是 命 名 接 口
12、的 GUID。在 COM 中 广 泛 地 使 用 GU ID 有 两 个 理 由:1.GUIDs 只 是 简 单 的 数 字,任 何 编 程 语 言 都 可 以 对 之 进 行 处 理;2.GUIDs 可 以 在 任 何 机 器 上 被 任 何 人 创 建,一 旦 完 成 创 建,它 就 是 唯 一 的。因 此,COM 开 发 人 员 可 以 创 建 自 己 特 有 的 GUIDs 而 不 会 与 其 它 开 发 人 员 所 创 建 的 GUIDs 有 冲 突。这样 就 消 除 了 集 中 授 权 发 布 GU IDs 的 必 要。/不 同 的 机 器 如 何 避 免 GUID的 冲 突?HR
13、ESULT是 COM 用 来 返 回 错 误 和 成 功 代 码 的 整 型 数 字。除 此 之 外,别 无 它 意,虽 然 以 H作 前 缀,但 没 有 句 柄 之 意。下 文 会 对 它 有 更 多 的 讨 论。最 后,COM库 是 在 你 使 用 COM时 与 你 交 互 的 操 作 系 统 的 一 部 分,它 常 常 指 的 就 是 COM本 身。但 是 为 了 避 免 混 淆 才 分 开 描 述 的。使 用 和 处 理 COM 对 象每 一 种 语 言 都 有 其 自 己 处 理 对 象 的 方 式。例 如,C+是 在 栈 中 创 建 对 象,或 者 用 new 动 态分 配。因 为
14、 COM必 须 独 立 于 语 言,所 以 COM库 为 自 己 提 供 对 象 管 理 例 程。下 面 是 对 COM 对象 管 理 和 C+对 象 管 理 所 做 的 一 个 比 较:创 建一个 新对象C+中,用 new 操 作 符,或 者 在 栈 中 创 建 对 象。COM 中,调 用 COM 库 中 的 API。删 除对象C+中,用 delete操 作 符,或 将 栈 对 象 踢 出。COM中,所 有 的 对 象 保 持 它 们 自 己 的 引 用 计 数。调 用 者 必 须 通 知 对 象 什 么 时 候 用 完 这 个 对 象。当 引 用 计 数 为 零 时,COM对 象 将 自
15、己 从 内 存 中 释 放。由 此 可 见,对 象 处 理 的 两 个 阶 段:创 建 和 销 毁,缺 一 不 可。当 创 建 COM对 象 时 要 通 知 COM库 使 用 哪 一 个 接 口。如 果 这 个 对 象 创 建 成 功,COM库 返 回 所 请 求 接 口 的 指 针。然 后 通 过 这 个 指针 调 用 方 法,就 像 使 用 常 规 C+对 象 指 针 一 样。创 建 COM 对 象为 了 创 建 COM对 象 并 从 这 个 对 象 获 得 接 口,必 须 调 用 COM库 的 API函 数,CoCreateInstance()。其 原 型 如 下:HRESULT CoC
16、reateInstance(REFCLSID rclsid,3 LPUNKNOWN pUnkOuter,DWORD dwClsContext,REFIID riid,LPVOID*ppv);以 下 是 参 数 解 释:rclsid:coclass的 CLSID,例如,可 以 传 递 CLSID_ShellLink创 建一个 COM 对象 来建 立快 捷 方 式。pUnkOut er:这 个参 数 只 用于 COM对 象 的聚合,利 用它向 现 有 的 coclass添 加新 方 法。参 数值 为 null表 示不使 用聚 合。/不 明白 啊?dwClsContext:表示 所使 用 COM 服
17、 务器 的 种类。本 文使 用 的 是最 简 单 的 COM 服 务器,一 个进 程 内(in-process)DLL,所 以传 递的 参数 值为 CLSCTX_INPROC_SERVER。注 意这 里不要 随意使 用 CLSCTX_ALL(在 ATL 中,它 是个 缺 省值),因 为在 没有 安装 DCOM 的 Windows95 系 统 上 会导 致失败。riid:请 求接 口的 IID。例如,可 以 传递 IID_IShellLink获得 IShellLink接口 指针。ppv:接 口指针 的 地 址。COM库通过 这 个 参数 返 回 请求 的接 口。当 你 调 用 CoCreateI
18、nstance()时,它 负 责 在 注 册 表 中 查 找 COM 服 务 器 的 位 置,将 服 务 器 加载 到 内 存,并 创 建 你 所 请 求 的 coclass实 例。以 下 是 一 个 调 用 的 例 子,创 建 一 个 CLSID_ShellLink对 象 的 实 例 并 请 求 指 向 这 个 对 象 IShellLink 接 口 指 针。HRESULT hr;IShellLink*pISL;hr=CoCreateInstance(CLSID_ShellLink,/coclass 的 CLSID NULL,/不是 用聚 合CLSCTX_INPROC_SERVER,/服 务器
19、 类 型IID_IShellLink,/接 口 的 IID(void*)&pISL);/指 向 接 口的指 针if(SUCCEEDED(hr)/用 pISL 调 用方 法 else /不 能创 建 COM 对 象,hr 为 出 错代 码 首 先 声 明 一 个 接 受 CoCreateInstance()返 回 值 的 HRESULT和 IShellLink 指 针。调 用CoCreateInstance()来 创 建 新 的 COM 对 象。如 果 hr 接 受 到 一 个 表 示 成 功 的 代 码,则 SUCCEEDED宏 返 回 TRUE,否 则 返 回 FALSE。FAILED是 一
20、 个 与 SUCCEEDED对 应 的 宏 用 来 检 查 失 败 代 码。删 除 COM 对 象前 面 说 过,你 不 用 释 放 COM 对 象,只 要 告 诉 它 们 你 已 经 用 完 对 象。IUnknown是 每 一 个COM对 象 必 须 实 现 的 接 口,它 有 一 个 方 法,Release()。调 用 这 个 方 法 通 知 CO M 对 象 你 不 再需 要 对 象。一 旦 调 用 了 这 个 方 法 之 后,就 不 能 再 次 使 用 这 个 接 口,因 为 这 个 COM 对 象 可 能 从 此就 从 内 存 中 消 失 了。如 果 你 的 应 用 程 序 使 用
21、许 多 不 同 的 COM 对 象,因 此 在 用 完 某 个 接 口 后 调 用 Release()就 显得 非 常 重 要。如 果 你 不 释 放 接 口,这 个 COM 对 象(包 含 代 码 的 DLLs)将 保 留 在 内 存 中,这 会4 增 加 不 必 要 的 开 销。如 果 你 的 应 用 程 序 要 长 时 间 运 行,就 应 该 在 应 用 程 序 处 于 空 闲 期 间 调 用CoFreeUnusedLibraries()API。这 个 API将 卸 载 任 何 没 有 明 显 引 用 的 COM服 务 器,因 此 这也 降 低 了 应 用 程 序 使 用 的 内 存 开
22、 销。继 续 用 上 面 的 例 子 来 说 明 如 何 使 用 Releas e():/像上 面一 样 创 建 COM 对 象,然 后,if(SUCCEEDED(hr)/用 pISL 调 用方 法/通 知 COM 对象 不再 使 用它pISL-Release();接 下 来 将 详 细 讨 论 IUnknown接 口。基 本 接 口 IUnknown每 一 个 COM 接 口 都 派 生 于 IUnknown。这 个 名 字 有 点 误 导 人,其 中 没 有 未 知(Unknown)接 口 的 意 思。它 的 原 意 是 如 果 有 一 个 指 向 某 COM 对 象 的 IUnknown
23、指 针,就 不 用 知 道 潜 在 的 对象 是 什 么,因 为 每 个 COM 对 象 都 实 现 IUnknown。IUnknown 有 三 个 方 法:/接 口 本 身 不 就 是 方 法 吗?AddRef()通 知 COM 对 象 增 加 它 的 引 用 计 数。如 果 你 进 行 了 一 次 接 口 指 针 的拷 贝,就 必 须 调 用 一 次 这 个 方 法,并 且 原 始 的 值 和 拷 贝 的 值 两 者 都 要 用 到。在 本 文 的 例 子 中 没有 用 到 AddRef()方 法;Releas e()通 知 COM 对 象 减 少 它 的 引 用 计 数。参 见 前 面
24、的 Release()示 例 代码 段;Query Interface()从 COM 对 象 请 求 一 个 接 口 指 针。当 coclass实 现 一 个 以 上的 接 口 时,就 要 用 到 这 个 方 法;前 面 已 经 看 到 了 Releas e()的 使 用,但 如 何 使 用 Qu ery Interface()呢?当 你 用CoCreateInstance()创 建 对 象 的 时 候,你 得 到 一 个 返 回 的 接 口 指 针。如 果 这 个 COM 对 象 实 现 一个 以 上 的 接 口(不 包 括 IUnknown),你 就 必 须 用 Query Interfa
25、ce()方 法 来 获 得 任 何 你 需 要 的 附加 的 接 口 指 针。Query Interface()的 原 型 如 下:HRESULT IUnknown:QueryInterface(REFIID iid,void*ppv);以 下 是 参 数 解 释:iid:所 请求的 接 口 的 IID。ppv:接 口指针 的 地 址,QueryInterface()通过 这 个 参数 在 成功 时返 回这 个 接 口。让 我 们 继 续 外 壳 链 接 的 例 子。它 实 现 了 IShellLink 和 IPer sistF ile 接 口。如 果 你 已 经 有 一 个IShellLin
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- COM 编程 入门
限制150内