microsoft / windows-rs

Rust for Windows
https://kennykerr.ca/rust-getting-started/
Apache License 2.0
10.23k stars 475 forks source link

Simplify derefencing `Ref` interface parameters #3027

Closed kennykerr closed 3 months ago

kennykerr commented 3 months ago

Building on #3025, this adds a simpler way to deal with nullable input parameters that are required but without forcing an expensive reference count bump. Here's an example of the new ok method:

#![allow(non_snake_case)]
use windows_core::*;

#[interface("09428a59-5b40-4e4c-9175-e7a78514316d")]
unsafe trait ITest: IUnknown {
    unsafe fn Print(&self) -> Result<()>;
    unsafe fn PrintOther(&self, other: Ref<ITest>) -> Result<()>;
}

#[implement(ITest)]
struct Test;

impl ITest_Impl for Test {
    unsafe fn Print(&self) -> Result<()> {
        println!("Test");
        Ok(())
    }
    unsafe fn PrintOther(&self, other: Ref<ITest>) -> Result<()> {
        other.ok()?.Print()
     // ^^^^^^^^^^^^^^^^^^^
    }
}

fn main() -> Result<()> {
    unsafe {
        let test: ITest = Test.into();
        test.Print()?;
        test.PrintOther(&test)?;
        Ok(())
    }
}

The ok method simplifies what would otherwise require something like this:

other.as_ref().ok_or(Error::from(E_POINTER))?.Print()