COM in the non-Windows world?

COM in the non-Windows world?

本文关键字:world non-Windows the in COM      更新时间:2023-10-16

希望这个问题不要太含糊。通过阅读COM规范和Don Box的Essential COM书,有很多关于"COM解决的问题"的讨论——它们听起来都很重要,都很相关,都是最新的。

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

编译器和编译器版本之间的二进制兼容性
  • 二进制组件重用
  • 编译应用程序,使其具有运行时依赖项,而不是加载时依赖项(以便即使缺少依赖项也能运行)
  • 从库自身语言以外的其他语言访问库功能
  • 对加载在不同进程的地址空间中的组件的开销相当低的远程过程调用
  • 等等(我相信名单还在列)
  • 我基本上只是想理解为什么CORBA在Linux上不像COM在Windows上一样(如果这有意义的话)。Linux上的软件开发是否遵循了与COM提出的基于组件的模型不同的哲学?

    最后,COM是C/C++吗?有好几次我看到一些人评论说COM已经过时了。NET,但没有真正解释它们的意思。

    在本文的剩余部分中,我将使用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实现的SOAP服务器进行通信(反之亦然)。既然您提到了开销,那么可能值得一提的是,WCF/SOAP往往会添加比COM更多的开销(根据具体情况,我看到过几乎等于开销的两倍)。

    要求的差异

    对于Linux,前两点的相关性往往相对较低。大多数软件都是开源的,许多用户习惯于在任何情况下从源代码构建。对于这些用户来说,二进制兼容性/重用几乎没有影响(事实上,相当多的用户可能会拒绝所有不是以源代码形式分发的软件)。尽管二进制文件通常是分布式的(例如,使用apt-get、yum等),但它们基本上只是缓存为特定系统构建的二进制文件。也就是说,在Windows上,你可能有一个单一的二进制文件可以在从Windows XP到Windows 10的任何东西上使用,但如果你使用apt get,比如Ubuntu 18.02,你安装的是一个专门为Ubuntu 18.02构建的二进制文件,而不是一个试图与Ubuntu 10(或其他)的所有内容兼容的二进制文件。

    当组件丢失时,能够加载和运行(功能降低)通常也是一个封闭源代码问题。闭源软件通常有几个版本,具有不同的功能,以支持不同的价格。供应商可以方便地构建主应用程序的一个版本,并根据提供/省略的其他组件提供不同级别的功能。

    不过,这主要是为了支持不同的价格水平。当软件是免费的,只有一个价格和一个版本:真棒版本。

    语言之间对库功能的访问再次倾向于更多地基于源代码而不是二进制接口,例如使用SWIG允许使用Python和Ruby等语言的C或C++源代码。同样,COM基本上解决了一个主要由源代码缺乏引起的问题;当使用开源软件时,问题根本不会从一开始就出现。

    低开销RPC到其他进程中的代码再次似乎主要源于封闭源代码软件。当/如果您希望Microsoft Excel能够使用某些内部";"东西";比如说,在Adobe Photoshop中,你可以使用COM让它们进行通信。这增加了运行时开销额外的复杂性,但当其中一段代码归微软所有,另一段由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总线可以(并且经常)用于许多与COM相同的事情。

    类似DCOM的系统

    COM还允许您使用DCOM(分布式COM)构建分布式系统。也就是说,在一个系统中,您在一台机器上调用一个方法,但(至少可能)在另一台机器中执行该调用的方法。这增加了更多的开销,但由于(正如上面关于D-bus所指出的)RPC基本上是通过连接到端部的代理/存根进行通信,所以以分布式方式做同样的事情非常容易。然而,开销的差异往往会导致系统需要如何设计才能良好工作的差异,因此,在分布式系统中使用与本地系统完全相同的系统的实际优势往往相当小。

    因此,开源世界提供了用于执行分布式RPC的工具,但通常不会努力使它们看起来与非分布式系统相同。CORBA是众所周知的,但通常被认为是大型和复杂的,所以(至少在我的经验中)目前的使用相当少。ApacheThrift提供了一些相同的通用类型的功能,但以一种更简单、更轻的方式。特别是,CORBA试图为分布式计算提供一套完整的工具(包括从身份验证到分布式计时的所有功能),Thrift更紧密地遵循Unix哲学,试图满足一个需求:从接口定义(用中性语言编写)生成代理和存根。如果希望用Thrift做那些类似CORBA的事情,你当然可以,但在构建内部基础设施的更典型的情况下,调用者和被调用者相互信任,你可以避免很多开销,只需继续处理手头的业务。同样,谷歌RPC提供了与Thrift大致相同的功能。

    OS X特定

    Cocoa提供了与COM非常相似的分布式对象。不过这是基于Objective-C的,我相信现在已经弃用了。

    苹果还提供XPC。XPC更多的是进程间通信,而不是RPC,所以我认为它更直接地与d-bus相比较,而不是与COM相比较。但是,与d-bus非常相似,它有很多与COM相同的基本功能,但形式不同,它更强调通信,而不太注重使事情看起来像本地函数调用(而且许多人现在更喜欢消息传递而不是RPC)。

    摘要

    开源软件在设计中有足够多的不同因素,因此对提供与微软COM在Windows上提供的功能相同的功能组合的需求较小。COM在很大程度上是一个试图满足所有需求的单一工具。在开源世界中,提供单一、包罗万象的解决方案的动力越来越小,而倾向于使用一套工具,每一套工具都能做好一件事,可以组合成一个满足特定需求的解决方案。

    由于更加商业化,Apple OS X可能(至少可以说)比大多数更纯粹的开源世界更接近COM。

    最后一个问题的快速答案是:COM还远远没有过时。微软世界中几乎所有的东西都是基于COM的,包括.NET引擎(CLR),以及新的Windows8.x的WindowsRuntime。

    以下是微软在其最新的C++页面中对.NET的评价欢迎回到C++(现代C++):

    C++正在经历一场复兴,因为权力再次为王。当程序员的工作效率很高时,像Java和C#这样的语言是很好的重要,但当功率和性能至关重要。实现高效率和高功率,尤其是在设备上硬件有限,没有什么能比得上现代C++。

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

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

    这在一定程度上是由于传统。早在CORBA或COM出现之前,UNIX开发人员就已经在做这样的事情了。这是"UNIX方式"。

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

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

    CORBA从未真正在开源世界中流行起来,因为最初的实现是专有的,而且成本高昂,当高质量的免费实现出现时,规范非常复杂,如果不需要的话,没有人愿意使用它

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

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

    然后是同一程序使用同一库的不同版本的情况。这在处理大型遗留程序时通常很有用,因为在这些程序中,升级所有内容的成本可能高得令人望而却步,但您无论如何都想使用新功能。有了COM,程序的旧部分就可以不用管了,因为新的库版本可以更容易地向后兼容。

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

    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机器,因为中间的网关是解决这个问题的常见的全球变暖解决方案。

    我的结论是,Linux到Windows的DCOM互操作性肯定不是不可能的,但除非你拿出钱包,否则这似乎是一个很少有人感兴趣谈论的话题!