1个不稳定版本
使用旧Rust 2015
0.2.0 | 2017年12月10日 |
---|
#15 in #com-interface
185KB
4.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接口玩耍。至少还有两个与COM支持相关的crate。
winapi-rs
包含Microsoft Windows API的各种COM接口定义。winrt-rust
为Rust提供对Windows Runtime (WinRT) API的支持。
理想情况下,这些crate可以很好地协同工作。如果您在使用这些crate与Intercom一起使用时遇到可用性问题,请随意创建一个描述问题的issue。
跨平台考虑
尽管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的过程宏属性基础上构建的。目前有四个属性可用
com_library!(LIBID, Classes...)
- 一个必需的属性,它实现了导出的DllGetClassObject
入口点以及CoClass
对ClassFactory
的实现。[com_interface(IID)]
- 一个属性,它指定了一个trait
或一个impl
作为COM接口。该属性将定义接口的虚表结构。[com_class(CLSID, Itfs...)]
- 定义在struct
上的一个属性。此属性实现了结构所需的CoClass
,这允许在对象上构造引用计数的ComBox<T>
实例。
依赖关系
~3MB
~58K SLoC