【问题标题】:COM in the non-Windows world?非 Windows 世界中的 COM?
【发布时间】:2013-12-11 11:59:02
【问题描述】:

希望这个问题不会太含糊。通读 COM 规范和 Don Box 的 Essential COM 书籍,有很多关于“COM 解决的问题”的讨论——它们听起来都很重要、相关且current

那么 COM 地址在其他系统(linux、unix、OSX、android)上是如何处理的?我在想这样的事情:

  • 编译器和编译器版本之间的二进制兼容性
  • 二进制组件重用
  • 编译应用程序,使其具有运行时依赖项而不是加载时依赖项(这样即使缺少依赖项也能运行)
  • 从图书馆自己的语言以外的语言访问图书馆功能
  • 对加载到不同进程的地址空间中的组件进行合理的低开销远程过程调用
  • 等等(我相信这个名单还在继续)

我基本上只是想理解为什么例如在 Linux 上 CORBA 不像 COM 是在 Windows 上的东西(如果这有意义的话)。 Linux 上的软件开发是否遵循与 COM 提出的基于组件的模型不同的理念?

最后,COM 是 C/C++ 的东西吗?有好几次我从人们那里听到 cmets 说 COM 被 .NET “淘汰”了,但没有真正解释他们的意思。

【问题讨论】:

  • en.wikipedia.org/wiki/D-Bus 提供了 COM 在 Linux 上所做的一些事情(让一个组件与另一个组件通信),尽管方式完全不同。

标签: c++ windows com binary-compatibility


【解决方案1】:

在本文的其余部分,我将使用 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 能够在 Adob​​e Photoshop 中使用一些内部“东西”,您可以使用 COM 让它们进行通信。这会增加运行时开销额外的复杂性,但是当其中一段代码归 Microsoft 拥有而另一段归 Adob​​e 所有时,这几乎就是你所坚持的。

源码级分享

然而,在开源软件中,如果项目 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。

【讨论】:

  • 有趣的观点。
  • COM 等共享标准相对于 SWIG 和 JNI 等标准的优势在于,在给定 N 种语言的情况下,它是一个 O(N) 解决方案而不是 O(N*N) 解决方案。 (这实际上与源代码与二进制文件无关)
  • 这真的很有趣,到目前为止我所做的任何 COM 阅读中都没有提到整个开放/封闭源代码方面,这很有意义。尽管如此,即使在您编译时,在您的系统(在 /lib 或 /usr/lib 中)上期望找到(已经编译)的共享对象上具有加载时依赖项的二进制文件并不少见(是吗?)项目本身来自源代码。在可执行文件上运行 ldd 可能会显示它取决于 libc.so、libtinfo.so、libdl.so、libpthread.so 等。如果编译器的版本不兼容,会不会出现链接问题?
  • 抱歉,已达到注释字符数限制 - 基本上,如果您用于编译应用程序的编译器与用于创建的编译器不兼容,例如libc 或 libpthread 之类的,你不会遇到问题吗?希望这个问题有意义..
  • 值得指出的是,用于 COM 接口的“中性”格式恰好是由 Microsoft C++ 编译器生成的虚拟函数表的布局(具有一组特定的编译器选项和指令)。虽然可以/曾经可以通过其他工具创建和使用 COM 组件,但 COM 可以被视为一种让 C++ 代码以类似于使用 C 绑定的方式与高级语言进行互操作的方法。如果您不想将 C++ 与其他语言混合使用,那么 COM 就不是天作之合。
【解决方案2】:

对最后一个问题的快速回答:COM 远未过时。 Microsoft 世界中的几乎所有东西都是基于 COM 的,包括 .NET 引擎(CLR),包括新的 Windows 8.x 的Windows Runtime

这是微软在最新的 C++ 页面Welcome Back to C++ (Modern C++) 中对 .NET 的评价:

C++ 正在经历复兴,因为权力再次为王。 当程序员的生产力低时,Java 和 C# 之类的语言就很好 重要,但它们在功率和性能时显示出它们的局限性 是最重要的。提高效率和功率,尤其是在设备上 硬件有限,没有什么能比得上现代 C++。

PS:对于一个在 .NET 上投资超过 10 年的开发人员来说,这有点令人震惊:-)

【讨论】:

  • re:c++ 回来了——是的,这似乎是今年 C++ 及 Beyond 会议的主题。也很高兴——我真的很喜欢 c++;回复:COM 并没有过时 - 是的,看,这正是我认为必须是这种情况,但是搜索“组件对象模型”产生的结果令人惊讶地很少,不是 MSDN 或某些大学课程PDF格式;搜索更具体的内容,例如“注册 com 对象”,效果更差,并且将搜索限制在过去一年基本上不会产生任何结果;所以我很感兴趣:为什么互联网上不谈论 COM?因此问题..
  • 问题是,在 Microsoft 世界中,.NET 是过去 10 年左右大多数开发的标准,尽管 COM 一直隐藏在其中,但它并不真正可见。托管 C++ 或 C++/CLI 也从未获得与 C# 相同的成功(部分原因是它们是 Microsoft 特定的扩展),而且 CLR 的互操作(P/Invoke、COM 与否)功能非常好。事实上,在 Windows 8.x 的 Windows 运行时中,它仍然不是很明显,因为大多数语言都有一个投影/绑定系统,包括 javascript。
  • 你的前两句话相互收缩。您的意思是“远未过时”(即根本没有过时)而不是“几乎过时”(即未完全过时但非常接近)?
  • @HarryJohnston - 嗯......我的意思是一点也不过时。我不是英语母语,所以我更新了答案:-)(PS:不要忘记在cmets中使用@,我恰好路过这里,今天才看到你的评论)。
  • @SimonMourier:奇怪;我的理解是,用户会根据自己的答案收到所有 cmets 的通知。至少,它对我来说是这样的。
【解决方案3】:

在 Linux 世界中,更常见的是开发静态链接的组件,或者在单独的进程中运行并通过管道文本(可能是 JSON 或 XML)来回通信的组件。

其中一些是由于传统。早在 CORBA 或 COM 出现之前,UNIX 开发人员就一直在做这样的事情。这是“UNIX 方式”。

正如 Jerry Coffin 在他的回答中所说,当您拥有一切的源代码时,二进制接口就没有那么重要了,实际上只会让一切变得更加困难。

COM 是在个人计算机比现在慢得多的时候发明的。在那些日子里,将组件加载到应用程序的进程空间中并调用本机代码通常是实现合理性能所必需的。现在,解析文本和运行解释脚本已经不是什么可怕的事情了。

CORBA 从未真正在开源世界中流行起来,因为最初的实现是专有且昂贵的,而且当高质量的免费实现可用时,规范已经非常复杂,如果不使用它就没有人愿意使用它。 t 必须这样做。

【讨论】:

  • 谢谢。很好奇您所说的计算机现在速度快得多,因此出于性能原因不需要在应用程序的进程空间中加载组件 - 对于 RAM 有限的移动设备,性能问题是否仍然不相关(甚至可能更重要) ?或者节省 CPU 周期(通过运行本机代码)可能有助于延长电池寿命?
  • 即使是便宜的智能手机也比 1990 年代的 PC 强大许多倍。在某些应用程序(例如 3D 游戏)中,使用本机代码仍然很重要,但动态加载来自多个供应商的组件在此类应用程序中并不常见。 Android 应用程序在虚拟机上运行; iOS 应用程序使用面向对象的运行时。许多智能手机应用实际上只是网页视图,带有基于 HTML/CSS 的 UI 运行 Javascript 代码。
【解决方案4】:

在很大程度上,COM解决的问题在Linux上被简单地忽略了。

确实,当您有可用的源代码时,二进制兼容性就不那么重要了。但是,您仍然需要担心模块化和版本控制。如果两个不同的程序依赖于同一个库的不同版本,你需要以某种方式支持它。

然后是同一个程序使用同一个库的不同版本的情况。这在处理大型遗留程序时通常很有用,在这种情况下升级所有东西可能会非常昂贵,但无论如何您都想使用新功能。使用 COM,程序的旧部分可以不用管,因为新的库版本可以更容易地向后兼容。

此外,必须从源代码编译而不是二进制兼容性是一个巨大的麻烦。特别是如果您实际上正在开发软件,因为二进制不兼容意味着您必须更频繁地重新编译。如果大型 C++ 程序中的一小部分发生变化,您可能需要等待 30 分钟的重新编译。如果不同的部分是兼容的,只有改变的部分需要重新编译。

【讨论】:

    【解决方案5】:

    COM 和 DCOM 已经在 Windows 中出现了相当长的一段时间,Windows 开发人员自然而然地使用了这个强大的框架。

    我们现在处于跨平台时代,在将此类应用程序移植到其他平台时,我们面临着挑战,在许多情况下可以完全缓解或消除这些挑战,除非我们移植的应用程序不仅仅是一个简单的独立应用程序。

    如果您要处理运行在不同机器上的一整套模块,所有模块都使用 Windows 特定技术(例如 DCE/RPC、DCOM 甚至 Windows 命名管道)进行通信,那么您的工作就变得困难了一个数量级。

    DCE/RPC DCOM 和 windows 命名管道都是非常特定于 windows 的,不可移植,当然受 windows 安全访问控制。

    例如,任何熟悉 OPC DA(一种基于 DCOM 的工业自动化协议仍在使用,但现在被 OPC UA(避免 DCOM)取代))的人都会知道,如果客户端(或服务器)需要可用于 Linux!

    当然,这里似乎存在一些技术障碍,因为 MS 代码不在公共领域,但 Wine 等项目的 DCE/RPC 实现部分还不错,而且 MS 确实发布了一些协议文档。尝试搜索,您可能会发现很少的信息和开源产品或其他可以帮助您的产品。

    也许这里缺乏开源或负担得起的选择更多是由于法律问题 - 我想知道!

    一些更简单的解决方案只涉及在 Windows 机器上安装“网关服务”,以允许通过另一种方式访问​​该机器上的 DCOM 接口。如果 Windows 机器不属于不情愿的第 3 方,这很好,不幸的是,有时情况就是这样!!!我知道我们只会扔掉另一台 Windows 机器,因为中间的网关是解决该问题的常用全球变暖解决方案。

    我会得出结论,Linux 到 Windows DCOM 的互操作性当然不是不可能的,但它似乎确实是一个很少有人有兴趣谈论的话题,除非你掏出你的钱包!

    【讨论】:

      猜你喜欢
      • 2010-11-14
      • 1970-01-01
      • 2014-05-14
      • 1970-01-01
      • 1970-01-01
      • 2011-02-15
      • 2013-01-07
      • 2012-06-27
      • 2012-01-01
      相关资源
      最近更新 更多