6 个版本 (破坏性更新)
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.1.0 | 2019年10月1日 |
#101 in Windows API
77,275 每月下载量
在 592 个crate中使用(通过 com_macros)
70KB
1.5K SLoC
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的安全性以及为这些API编写安全包装的任务留给了程序员。
您可以在安全性指南中了解更多关于该库提供哪些保证。
现有crate
有许多现有的Rust crate可以帮助处理COM交互。根据您的用例,您可能会发现这些crate更适合您的需求。例如,我们有
构建
此库仅适用于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
~35K SLoC