在本文的其余部分,我将使用 Linux 作为开源软件的示例。在我提到“Linux”的地方,它通常是一种简短/简单的方式来指代开源软件,而不是任何特定于 Linux 的东西。
COM 与 .NET
COM 实际上并不局限于 C 和 C++,而且 .NET 实际上并没有取代 COM。但是,.NET 在某些情况下确实提供了 COM 的替代方案。 COM 的一种常见用途是提供控件(ActiveX 控件)。 .NET 提供/支持其自己的控件协议,允许某人用一种 .NET 语言编写控件,并从任何其他 .NET 语言使用该控件——或多或少与 COM 在 .NET 之外提供的东西相同世界。
同样,.NET 提供 Windows Communication Foundation (WCF)。 WCF 实现了 SOAP(简单对象访问协议)——它可能一开始很简单,但充其量发展成为不那么简单的东西。无论如何,WCF 提供了许多与 COM 相同的功能。尽管 WCF 本身特定于 .NET,但它实现了 SOAP,并且使用 WCF 构建的 SOAP 服务器可以与没有 WCF 实现的服务器通信(反之亦然)。既然您提到了开销,那么可能值得一提的是,WCF/SOAP 往往会比 COM 增加更多的开销(我见过几乎等于开销的两倍,具体取决于具体情况)。
需求差异
对于 Linux,前两点的相关性往往相对较低。大多数软件都是开源的,许多用户在任何情况下都习惯于从源代码构建。对于这样的用户,二进制兼容性/重用几乎没有影响(事实上,相当多的用户可能会拒绝所有不是以源代码形式分发的软件)。尽管二进制文件通常是分布式的(例如,使用 apt-get、yum 等),但它们基本上只是缓存为特定系统构建的二进制文件。也就是说,在 Windows 上,您可能有一个二进制文件可用于从 Windows XP 到 Windows 10 的任何设备,但如果您在 Ubuntu 18.02 上使用 apt-get,则您正在安装专门为 Ubuntu 18.02 构建的二进制文件,而不是一个试图与所有回到 Ubuntu 10(或其他)的东西兼容。
在缺少组件时能够加载和运行(功能降低)通常也是闭源问题。闭源软件通常有多个版本,具有不同的功能以支持不同的价格。供应商可以方便地构建一个版本的主应用程序,并根据提供/省略的其他组件提供不同级别的功能。
不过,这主要是为了支持不同的价格水平。当软件免费时,只有一个价格和一个版本:awesome edition。
语言之间对库功能的访问再次倾向于更多地基于源代码而不是二进制接口,例如使用SWIG 允许使用来自 Python 和 Ruby 等语言的 C 或 C++ 源代码。同样,COM 基本上解决了主要是由于缺少源代码而引起的问题。使用开源软件时,根本不会出现问题。
在其他进程中编码的低开销 RPC 似乎主要源于闭源软件。当/如果您希望 Microsoft Excel 能够在 Adobe Photoshop 中使用一些内部“东西”,您可以使用 COM 让它们进行通信。这会增加运行时开销和额外的复杂性,但是当其中一段代码归 Microsoft 拥有而另一段归 Adobe 所有时,这几乎就是你所坚持的。
源码级分享
然而,在开源软件中,如果项目 A 有一些对项目 B 有用的功能,那么您可能会看到(至多)项目 A 的一个分支,以将该功能转换为一个库,然后链接到项目 A 的其余部分和项目 B,很可能也链接到项目 C、D 和 E 中——所有这些都没有增加 COM、跨过程 RPC 等的开销。
现在,请不要误会我的意思:我并不是要充当开源软件的代言人,也不是说封闭源代码很糟糕,而开放源代码总是显着优越。我的意思是,COM 主要是在二进制级别定义的,但是对于开源软件,人们倾向于更多地处理源代码。
当然,SWIG 只是在源代码级别支持跨语言开发的众多工具中的一个示例。虽然 SWIG 被广泛使用,但 COM 在一个相当关键的方面与它不同:使用 COM,您可以用一种单一的中性语言定义一个接口,然后生成一组适合该接口的语言绑定(代理和存根)。这与 SWIG 完全不同,在 SWIG 中,您直接从一种源语言匹配到一种目标语言(例如,绑定以使用 Python 中的 C 库)。
二进制通信
在某些情况下,至少拥有一些类似于 COM 提供的功能是有用的。这些导致了在更大程度上类似于 COM 的开源系统。例如,许多开源桌面环境使用/实现 D-bus。 COM 主要是一种 RPC 类型的东西,而 D-bus 主要是一种在组件之间发送消息的约定方式。
然而,D-bus 确实指定了它称为对象的东西。它的对象可以有方法,您可以向这些方法发送信号。尽管 D-bus 本身主要根据消息传递协议定义了这一点,但编写代理对象是相当简单的,这使得在远程对象上调用方法看起来很像在本地对象上调用方法。最大的区别在于 COM 有一个“编译器”,它可以接受协议的规范,并自动为您生成这些代理(以及在远端接收消息的相应存根,并根据它调用适当的函数已收到)。这不是 D-bus 本身的一部分,但是人们已经编写了工具来获取(例如)接口规范并根据该规范自动生成代理/存根。
因此,尽管两者并不完全相同,但 D-bus 可以(并且经常)用于许多与 COM 相同的事情。
类似于 DCOM 的系统
COM 还允许您使用 DCOM(分布式 COM)构建分布式系统。也就是说,您在一台机器上调用方法,但(至少可能)在另一台机器上执行调用的方法的系统。这增加了更多的开销,但是由于(正如上面关于 D-bus 所指出的)RPC 基本上是与连接到末端的代理/存根进行通信,因此以分布式方式做同样的事情非常容易。然而,开销的差异往往会导致系统需要如何设计才能正常工作的差异,因此在分布式系统中使用与本地系统完全相同的系统的实际优势往往相当小。
因此,开源世界提供了用于执行分布式 RPC 的工具,但通常不会努力使它们看起来与非分布式系统相同。 CORBA 是众所周知的,但通常被认为是庞大而复杂的,因此(至少根据我的经验)当前的使用相当少。 Apache Thrift 提供了一些相同的通用类型的功能,但以一种更简单、更轻量级的方式。特别是,CORBA 试图为分布式计算提供一套完整的工具(包括从身份验证到分布式计时的所有内容),Thrift 更紧密地遵循 Unix 哲学,试图满足一个需求:从接口定义(用中性语言编写)。如果你想用 Thrift 做类似 CORBA 的事情,你无疑可以,但是在构建调用者和被调用者相互信任的内部基础架构的更典型情况下,你可以避免大量开销和继续手头的业务。同样,google RPC 提供与 Thrift 大致相同的功能。
OS X 特定
Cocoa 提供了与 COM 非常相似的distributed objects。这是基于 Objective-C 的,但我相信它现在已被弃用。
Apple 还提供XPC。 XPC 更多是关于进程间通信而不是 RPC,所以我认为它更直接地与 D-bus 相比,而不是与 COM。但是,很像 D-bus,它具有许多与 COM 相同的基本功能,但形式不同,它更强调通信,而不是使事情看起来像本地函数调用(而且现在许多人更喜欢消息传递而不是 RPC )。
总结
开源软件在其设计中具有足够多的不同因素,因此对于提供与 Microsoft 的 COM 在 Windows 上提供的相同功能组合的东西的需求较少。 COM 在很大程度上是一个试图满足所有需求的单一工具。在开源世界中,提供单一、包罗万象的解决方案的动力较少,而更倾向于使用一套工具,每个工具都做好一件事,可以组合成满足特定需求的解决方案。
由于更面向商业,Apple OS X 可能(至少可以说)比大多数更纯粹的开源世界更接近于 COM。