COM 客户端连接 COM 服务器所需的文件是什么(进程外方案)



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

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

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

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

  3. xxx_p.c ?

  4. dlldata.c ?

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

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

在最简单的形式中,COM 只是vtable二进制协定加上所有接口的母:IUnknown。COM 是一种在没有源代码的情况下重用代码的方法,它与组件一起,它是某种动态强制转换机制。只要我知道你支持的coclass(它们的CLSID),它们公开的接口(它们的IID),以及这些接口的方法布局,它们的参数,顺序,类型等,我可以使用你的COM服务器。

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

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

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

因此,如果您支持IDispatch,提供 TLB(类型库)并将所有类型限制为自动化类型,那么您不需要处理封送处理,您不需要代理和存根,即使在进程外场景中,您也可以忘记所有这些,因为Microsoft自动实现它。过去,我们曾经将"oleaut32.dll"称为"通用编组"。

双接口是同时支持IUnknown和派生和IDispatch的接口。它们主要是为了同时支持 C/C++ 客户端自动化客户端而存在的。在 C/C++ 中使用自动化(BSTR、VARIANT 等)有点痛苦,因为它们最初不是用来供 C/C++ 客户端使用的......注意 Microsoft 提出了C++智能包装类:使用 ATLCComBSTRCComVARIANT,或使用 Windows SDK_variant_t_bstr_t

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

Box, Don. Essential COM. Addison-Wesley, 1998, pp. 350:

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

也许最普遍的此类语言是基于HTML的脚本 在 Web 浏览器或 Web 服务器的上下文。在这两个方面 在这种情况下,脚本文本以嵌入在 HTML 文件中的原始形式存储, 周围的运行时动态执行脚本文本作为 解析 HTML。为了提供丰富的编程环境,这些 环境允许脚本调用 COM 对象上的方法,这些方法可能 在脚本文本本身中创建,也可能在 HTML 中的其他地方创建 流(例如,也是网页一部分的控件)。在这些 环境,目前无法使用类型库或 其他先验方法,为运行时引擎提供描述 正在使用的接口。这意味着对象本身 必须协助口译员将原始脚本文本翻译成 有意义的方法调用。

允许从 解释性环境,如Visual Basic Script和JavaScript, COM 定义一个接口,用于表达 解释。


Tl;DR:有两种方法可以在COM中执行所有操作(忽略IInspectable和双接口):


  1. IUnknown标准虚拟方法调用。 快速,无需额外代码。 需要客户端调用上的编译时接口信息(.h 或 .tlb)

  2. IDispatch"后期绑定"。 缓慢,大量的解释代码。 无需客户端编译或接口规范。

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

最新更新