COM如何实现语言互操作?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了COM如何实现语言互操作?相关的知识,希望对你有一定的参考价值。

我了解COM如何实现与编译器无关的C ++代码,因为它通过谨慎使用C ++语言的哪些功能来定义ABI。只是C ++代码以一种非常聪明的方式与C ++代码对话。但是我仍然不明白它如何允许与C#或Java语言进行语言互操作。

边界在哪里?我现在唯一的解释是,语言编译器本身必须对COM给予特殊支持,以便它可以生成正确的汇编代码,以允许调用方/被调用方之间进行准确的通信。

答案

由于您已经用WinRT标记了您的问题,所以我想您要特别询问WinRT语言投影如何实现这一点。在这种情况下,所有语言都必须有某种方式将其自然语言结构映射到WinRT定义的COM ABI。该ABI源自ECMA 335标准中编码的元数据,并应用了特殊规则将抽象元数据转换为具体的ABI。自然有不同的方法可以实现这一目标。 CLR本身已更新,以支持C#中的WinRT。 Visual C ++编译器已(使用语言扩展)进行了更新,以通过C ++ / CX支持WinRT。 C ++ / WinRT方法非常不同,因为它只需要一个标准的C ++编译器,并且有关WinRT的所有知识都是通过一个标准的C ++仅标头库提供的。其他语言可能采用不同的方法,但最终,他们必须就元数据中表示的类型转换为基于COM的ABI上的对象和虚拟函数调用的方式达成共识。

尽管目前尚无很好的文档记录此过程,但是C ++ / WinRT是唯一的开源语言预测之一,因此对于那些需要了解WinRT如何在幕后工作的人来说,它是一个有用的参考实现。

https://github.com/microsoft/cppwinrt

另一答案

“类型库”使不同语言之间的COM组件互操作。

https://docs.microsoft.com/en-us/windows/desktop/midl/com-dcom-and-type-libraries

类型库(.tlb)是一个二进制文件,用于存储有关COM或DCOM对象的属性和方法的形式为在运行时可供其他应用程序访问。使用类型库,应用程序或浏览器可以确定对象的接口支持并调用对象的接口方法。这可能发生即使对象和客户端应用程序是用不同的方式编写的编程语言。 COM / DCOM运行时环境也可以使用类型库,以提供自动的跨部门,跨进程,和跨机器封送处理类型的接口库。

用于语言互操作的另一种方法(例如C ++将对象投影到javascript)是COM对象可以实现IDispatch

另一答案

当然不是魔术。

COM为语言互操作设置规则。只是合同,还有一些有用的工具。每种想要支持COM的语言都必​​须找到一种自己遵守规则的方法。它们都必须以一种或另一种方式提供自己的兼容机制。

就C ++而言,这些规则似乎是免费提供的,但请注意,这里有一个警告:语言标准未指定类和虚函数的布局和机制。 COM模仿的方法是虚拟调用(“ VTable”)的一种极为常见的实现,并且COM遵循Microsoft编译器使用的确切布局。但是您可以拥有一个完全有效的C ++编译器,其中带有虚函数的类将与COM布局不兼容。只是没有人这样做,至少在Windows编译器中没有。因此,即使在C ++中,编译器也会有一些“中间会议”。

在C语言中,您必须手动完成整个操作。其他语言可能允许您做同样的事情(当然是汇编程序)。

为了帮助编译的语言交换有关特定合同的信息,COM提供了类型库和读取它们的机制。想要利用它们的编译器或语言也必须“碰面”并学习如何处理它们(例如,Microsoft C ++ #import指令; VB6 Libraries菜单)。

并不是所有的语言都可以支持您在COM中可以做的所有事情,因为在某种程度上(在更晦涩的功能中),实现该语言的支持所获得的投资回报并没有实现。每种语言都必须选择自己的限制。您可以在COM中做很多事情(阅读IDL规范),而VB6则做不到。

由于在类似脚本的语言中遵循COM规则是不切实际和不可能的,因此COM提供了更高级的方法(自动化),即使更受限制,它也更适合动态语言。但是,想要为自动化提供客户支持的语言实现者必须实现对IDispatch接口的理解,激活机制以及对其语言适当功能的翻译。想要为创建COM服务器提供支持的脚本语言必须更努力地工作,以代表用户脚本实现有效的COM IDispatch实现和独立的主机引擎。直到Microsoft在Windows脚本宿主中添加.SCR支持之前,甚至VBScript都无法做到这一点。再次“在中间开会”。

如果一种语言想同时支持纯COM和自动化,则他们需要加倍努力;对其中一项的支持不会自动为您提供对另一项的支持。

对于像C#这样的.NET语言,大多数工作都是在.NET运行时内部完成的,它是为本机COM和自动化完成的,它提供了实现交互所需的COM可调用包装器(CCW)和运行时可调用包装器(RCW)的实现使用COM,并处理COM的引用计数方法和.NET的GC方法之间的冲突。微软将所有工作都集中在一处,因此各个.NET语言设计人员都不必这样做。

所以,是的,语言实现者必须付出额外的努力才能为COM提供特殊的语言支持:遵循二进制布局规则,在需要时实现翻译层,和/或可能提供读取类型库的工具。

语言互操作性要求双方(呼叫者和被呼叫者)在某个地方“遇到中间人”。 COM只是一个规范,它为设计人员提供了一个中间立场,即“所有人都能相遇的地方”。

以上是关于COM如何实现语言互操作?的主要内容,如果未能解决你的问题,请参考以下文章

64 到 32 位互操作 - 如何?

如何指定我的 .NET 互操作应该使用哪个 COM 服务器?

在 C++ 中使用 COM 互操作对象

[转]Go与C语言的互操作

如何在 C# 和 C++ 之间进行互操作

互操作性如何工作