9个版本 (破坏性更新)
0.6.0 | 2021年10月25日 |
---|---|
0.5.0 | 2021年10月5日 |
0.4.0 | 2021年1月27日 |
0.3.0 | 2020年10月21日 |
0.0.2 | 2015年6月10日 |
#22 in Windows API
每月下载量 93,416
用于 632 个crate(7个直接使用)
50KB
728 行
COM
Rust中所有与COM编程相关事物的终点。
此库向用户公开了各种宏、结构和函数,以便以规范的方式生成和消耗COM组件。
🚨 🚨 🚨 注意 此crate目前正在积极开发中,因为我们正在决定一个稳定的API。 🚨 🚨 🚨
什么是COM?
COM 是一个平台无关的、分布式的、面向对象的系统,用于创建可以交互的二进制软件组件。
COM已被 WinRT 取代,WinRT基于COM,提供了关于二进制接口的更多保证。因此,如果您不确定是否需要使用COM,您可能不应该使用。
用法
定义COM接口
要通過接口消耗或生成COM组件,您首先需要生成该接口的Rust表示。interfaces
宏是自动生成此Rust表示的主要工具。
com::interfaces! {
#[uuid("00000000-0000-0000-C000-000000000046")]
pub unsafe interface IUnknown {
fn QueryInterface(
&self,
riid: *const IID,
ppv: *mut *mut c_void
) -> HRESULT;
fn AddRef(&self) -> u32;
fn Release(&self) -> u32;
}
#[uuid("EFF8970E-C50F-45E0-9284-291CE5A6F771")]
pub unsafe interface IAnimal: IUnknown {
fn Eat(&self) -> HRESULT;
}
}
简短说明:此宏为IUnknown和IAnimal生成VTable布局,以及正确的 Clone
和 Drop
实现。
消耗COM组件
与COM组件的交互始终通过接口指针(VTable的指针的指针)进行。
use com::run_time::{create_instance, init_runtime};
// Initialises the COM library
init_runtime().expect("Failed to initialize COM Library");
// Get a COM instance's interface pointer, by specifying
// - The CLSID of the COM component
// - The interface of the COM component that you want
// create_instance returns an IAnimal interface in this case.
let mut cat = create_instance::<IAnimal>(&CLSID_CAT_CLASS).expect("Failed to get a cat");
// All IAnimal methods will be available.
// Because we are crossing an FFI boundary, all COM interfaces are marked as unsafe.
// It is the job of the programmer to ensure that invariants beyond what the COM library guarantees are upheld.
unsafe { cat.Eat(); }
有关用法和安全性的更多信息,请参阅 文档。
生成COM组件
与消耗相比,生成COM组件要复杂得多,因为我们必须支持许多功能。在此,我们将向您展示如何生成我们的示例之一,即 BritishShortHairCat
。
- 定义包含所有所需用户字段的类。
- 指定类实现的每个接口。您必须列出接口的父接口,除非指定了IUnknown,如果没有指定父接口,则假定IUnknown(例如,
: MyInterface(MyParentInterface(MyGrandParentInterface)), MyOtherInterface
)。
- 在类中实现必要的接口。
use com::class;
com::class! {
pub class BritishShortHairCat: ICat(IAnimal), IDomesticAnimal(IAnimal) {
num_owners: u32,
}
impl IDomesticAnimal for BritishShortHairCat {
fn Train(&self) -> HRESULT {
println!("Training...");
NOERROR
}
}
impl ICat for BritishShortHairCat {
fn IgnoreHumans(&self) -> HRESULT {
println!("Ignoring Humans...");
NOERROR
}
}
impl IAnimal for BritishShortHairCat {
fn Eat(&self) -> HRESULT {
println!("Eating...");
NOERROR
}
}
}
有关用法和安全性的更多信息,请参阅 文档。
安全性
虽然COM指定了方法调用的ABI细节,但在确保这些方法调用的安全性方面做得很少。因此,程序员需要自行验证COM API的安全性,并编写安全的包装器。
您可以在安全性指南中了解更多关于该库提供的保证信息。
现有crates
有许多现有的Rust crates可以帮助进行COM交互。根据您的用例,您可能发现这些crates更适合您的需求。例如,我们有
构建
这个库仅适用于Windows,所以最容易的贡献方式是在Windows机器上。您可以通过以下方式执行示例
cd examples\basic
cargo run --release
如果您在Mac或Linux机器上,您仍然可以通过从项目的根目录运行以下命令来更改内容并检查它们是否编译
cargo check --target=x86_64-pc-windows-msvc
贡献
有关贡献的更多信息,请参阅贡献文档
行为准则
本项目已采用Microsoft开源行为准则。您可以在行为准则文档中了解更多信息。
常见问题解答
是否有IDL支持?
作为基础,我们正在尝试创建一个不一定依赖于IDL文件的库。但是,它将在未来改进中。我们将有一个命令行工具,该工具可以将IDL解析为所需的宏。
是否有进程外COM支持?
目前,我们仅支持生成进程内COM组件。此外,COM组件的生成只能以DLL格式进行。将会有计划启用进程外COM生成以及以.EXE格式生成。
依赖项
~1.5MB
~36K SLoC