COM如何实现语言互操作?

时间:2019-02-08 05:01:18

标签: windows com windows-runtime c++-winrt

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

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

3 个答案:

答案 0 :(得分:1)

通过“类型库”可以在不同语言之间互操作COM组件。

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

  

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

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

答案 1 :(得分:1)

那当然不是魔术。

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

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

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

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

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

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

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

对于C#等.NET语言,.NET运行时内部的大多数工作都是针对本机COM和自动化完成的,这提供了COM Callable Wrappers(CCW)和Runtime Callable Wrappers(RCW)的实现。与COM进行交互,并处理COM的引用计数方法与.NET的GC方法之间的冲突。微软将所有工作都集中在一处,因此.NET语言设计人员不必这样做。

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

Language Interop要求双方(呼叫者和被呼叫者)“相约在某个地方”。 COM只是一个规范,它为设计人员提供了一个中间立场,即“所有人可以相遇的地方”。

答案 2 :(得分:0)

既然您已经用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/xlang/tree/master/src/tool/cpp/cppwinrt