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 中使用
185KB
3.5K SLoC
Intercom
Rust中编写COM组件的实用工具
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提供了两个指导原则
- 存在Intercom API/约定的子集,允许用户编写可在任何平台上编译和使用的Intercom组件。
- 在具有自己的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
入口点以及ClassFactory
的CoClass
。[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