4个版本 (破坏性更新)

0.4.0 2022年7月2日
0.3.0 2019年10月1日
0.2.0 2017年12月10日
0.1.0 2017年11月5日

#20 in #com-interface


intercom 中使用

MIT 协议

185KB
3.5K SLoC

Intercom

Rust中编写COM组件的实用工具

crates.io Build Status codecov

Intercom允许用户使用Rust编写可重用的组件,这些组件与组件对象模型接口标准二进制兼容。这些组件可以用于任何支持静态COM组件的语言,包括C++、C#和VB.Net。

示例

Rust COM服务器

pub use intercom::*;

com_library! {
    class Calculator
}

#[com_class(Calculator)]
struct Calculator {
    value: i32
}

#[com_interface]
impl Calculator {
    pub fn add(&mut self, value: i32) -> ComResult<i32> {
        self.value += value;
        Ok(self.value)
    }
}

C# COM客户端

class Program
{
    [STAThread]
    static void Main( string[] args )
    {
        var calc = new Calculator.Interop.Calculator();
        calc.Add( 10 );
        var result = calc.Add( 100 );
        Console.WriteLine( result );
    }
}

其他crate

Intercom并不是Rust第一次玩COM接口。至少还有两个crate与COM支持相关。

  • winapi-rs 包含Microsoft Windows API的各种COM接口定义。
  • winrt-rust 为Rust提供了Windows Runtime (WinRT) API的支持。

理想情况下,这些crate可以很好地协同工作。如果您在使用这些crate与Intercom一起时遇到可用性问题,请随时创建一个问题,描述您遇到的问题。

跨平台考虑

虽然COM传统上是Windows技术,但Intercom旨在提供一个平台无关的方式来执行Rust和其他语言之间的方法调用。这为Intercom提供了两个指导原则

  1. 存在Intercom API/约定的子集,允许用户编写可在任何平台上编译和使用的Intercom组件。
  2. 在具有自己的COM API的平台上,Intercom组件与平台API和预期兼容。

在实践中,这意味着例如在Windows上,Intercom将使用 SysAllocString 分配字符串。这使得Intercom组件可以与Windows技术(如.Net COM互操作)一起使用。

但是,平台无关的子集将需要使用 IIntercomAllocator 分配和释放字符串。

技术细节

背景

COM(组件对象模型)是基于虚拟表(也称为调度表)的使用。有一个导出的符号,即DllGetClassObject,客户端(使用COM模块的代码片段)使用它来获取初始的IClassFactory接口。一旦客户端有了IClassFactory接口,其余的方法调用就可以通过COM接口来完成。

每个COM接口由一个包含虚拟表和服务器(实现接口的库)所需数据的对象表示。当客户端尝试在接口上调用方法时,它将使用虚拟表来解析正确的方法地址,并使用Pascal调用约定(在大多数C++编译器中为__stdcall,在Rust中为"stdcall")进行调用。

实现

Intercom库是基于Rust的proc macro属性构建的。目前有四个属性可用

  • com_library!(LIBID, Classes...) - 一个必需的属性,它实现了导出的DllGetClassObject入口点以及ClassFactoryCoClass
  • [com_interface(IID)] - 一个属性,指定了一个trait或一个impl作为COM接口。该属性会导致为接口定义虚拟表结构。
  • [com_class(CLSID, Itfs...)] - 定义在struct上的属性。该属性实现了结构所需的CoClass,这允许在对象上构建引用计数的ComBox<T>实例。

lib.rs:

定义Intercom库的过程宏属性。

这些宏实现了各种底层项,使得关联类型可以在COM接口协议上实例化和调用。

用户不应直接依赖于这个crate,而应依赖于主要的intercom crate。

将它们分成两个crate是Rust的人工限制。定义过程宏的crate除了过程宏之外不能导出任何其他内容。

依赖项

~2.5MB
~53K SLoC