0

我想了解本文中提到的文件的用途,并将知识链接到我当前的 COM 服务器和 COM 客户端场景,以便我可以实现我的 COM 服务器以使用 COM 服务器:这个

我有一个 COM 服务器,它是一个在后台运行的 exe 或服务。现在,我知道有一个继承自 IUnknown 和 IDispatch 的公开接口。此外,我还生成了以下文件:

  1. xxx_i.c 定义了所有的 CLSID 和 IID

  2. xxx_i.h 定义了接口支持的所有方法

  3. xxx_pc ?

  4. dlldata.c ?

我现在使用自动化方式 IDispatch -> Invoke() 来访问接口方法。尽管这种方式在不使用上述任何文件的情况下似乎可以正常工作,但我仍然想了解它们的用途,同时使用常规方式 IUnknown -> QueryInterface() 来访问这些方法。

由于我是 COM 世界的新手,任何建议的阅读将不胜感激!谢谢!

4

2 回答 2

1

在最简单的形式中,COM 只是vtable二进制合约加上所有接口之母:IUnknown. COM 是一种无需源代码即可重用代码的方法,使用组件,它是某种动态转换机制。如果我知道你支持的类(它们的CLSID)、它们公开的接口(它们的IID),以及这些接口的方法布局、它们的参数、顺序、类型等,我可以使用你的 COM 服务器。

但是为了简化 COM 客户端和 COM 服务器之间的“通信”,您可以/应该使用一些标准机制/文档并添加工具,以便无需任何努力即可处理诸如编组(=序列化)之类的管道工作。这在进程外的情况下至关重要,对进程内的情况不太重要(我将在这里避开“公寓”的概念......)

所以,你会在 COM 中找到的很多东西(如注册、工具、IDL、类型库等)实际上是可选的,但也非常有用(所以它们最终会成为强制性的)。(对于“接口语言定义”)之类的目的idl是定义并向您的 COM 客户端公开您的 COM 服务器支持的内容,以便工具可以为您和您的客户端自动生成大量代码(.c、.h、.tlb )。请注意,如果没有在 idl 中定义它们,没有什么可以阻止您实现接口或 coclass。没有任何义务要求您提供 .idl 或 .tlb。在这种情况下,只有知道它们的 IID、方法布局等,我才能使用它们。

然后,在 之上IUnknown,微软创建了一个通用接口IDispatch(这也称为“自动化”,或“后期绑定”,而不是“早期绑定” IUnknown),当时针对 VB/VBA 客户端(甚至在 VBScript 之前, JScript 和许多其他 COM 客户端,.NET 支持 IUnknown 和 IDispatch)。IDispatch,如果你走那条路,可能是你必须实现的最后一个接口,因为它的语义允许完全发现和调用任何方法,只要它支持一组有限的已定义数据类型,即“自动化类型”:BSTR ,变体等。

所以,如果你支持IDispatch,提供一个 TLB(类型库)并将所有类型限制为自动化类型,那么你不需要处理封送处理,你不需要代理和存根,你可以忘记这一切,即使在输出-进程方案,因为 Microsoft 会自动实现这一点。过去,我们曾经将“oleaut32.dll”称为“通用编组器”。

双接口是同时支持IUnknown和派生的接口IDispatch。它们的存在主要是为了同时支持 C/C++ 客户端自动化客户端。在 C/C++ 中使用自动化(BSTR、VARIANT 等)有点痛苦,因为它们最初不打算由 C/C++ 客户端使用……注意微软提出了 C++ 智能包装类:CComBSTRand CComVARIANTwith ATL,或_variant_tand _bstr_twith Windows SDK。

于 2019-04-28T18:36:04.413 回答
0

阅读材料的请求超出了 StackOverflow 的范围,但我不禁推荐Don Box 的开创性作品:Essential COM,它已印刷并在其他地方作为电子书提供。以下是 Don 对该主题的描述:

盒子,唐。必不可少的 COM。Addison-Wesley,1998 年,第 350 页:

COM 基于在开发时对接口定义有先验知识的客户端程序。这可以通过 C++ 头文件(对于 C++ 客户端)或通过类型库(对于 Java 和 Visual Basic 客户端)来完成。一般来说,这不是问题,因为用这些语言编写的程序在部署之前通常会经历某种编译阶段。有些语言在开发时不会经过这样的编译阶段,而是以源代码形式部署以在运行时进行解释。

此类语言中最普遍的可能是基于 HTML 的脚本语言(例如 Visual Basic Sc​​ript、JavaScript),它们在 Web 浏览器或 Web 服务器的上下文中执行。在这两种情况下,脚本文本都以嵌入在 HTML 文件中的原始形式存储,并且在解析 HTML 时,周围的运行时动态执行脚本文本。为了提供丰富的编程环境,这些环境允许脚本调用 COM 对象上的方法,这些对象可能是在脚本文本本身中创建的,也可能是在 HTML 流中的其他地方创建的(例如,也是网页一部分的控件)。在这些环境中,目前不可能使用类型库或其他先验手段来为运行时引擎提供所使用接口的描述。

为了允许从解释环境(如 Visual Basic Sc​​ript 和 JavaScript)中使用对象,COM 定义了一个接口来表达解释的功能。


Tl; dr:在 COM 中有两种方法可以做所有事情(忽略IInspectable和双接口):

  1. IUnknown
    标准虚拟方法调用。快速,无需额外代码。需要客户端调用上的编译时接口信息(.h 或 .tlb)
  2. IDispatch
    “后期装订”。缓慢,大量的解释代码。无需客户端编译或接口规范。

实际上,除非您是从 VBA、VBScript 调用或有一些旧的 VB6 客户端,否则您最好IUnknown只坚持使用。

于 2019-04-28T17:37:48.200 回答