2 releases

new 0.1.1 Apr 30, 2024
0.1.0 Jun 12, 2023

#1012 in Rust patterns

36 downloads per month
Used in vst3

MIT/Apache

43KB
754 lines

com-scrape-types

Cargo Docs

Support code for bindings generated by com-scrape.

License

com-scrape-types is distributed under the terms of both the MIT license and the Apache license, version 2.0. Contributions are accepted under the same terms.


lib.rs:

Support types and traits for bindings generated by com-scrape.

ComPtr and ComRef are smart pointers for interacting with COM objects (calling methods, casting between interfaces, and managing reference counts). The Class trait can be used for defining COM classes in Rust, and ComWrapper is a smart pointer used for instantiating those classes.

Reference counting

COM objects are reference-counted. The ComPtr and ComRef smart pointers manage this automatically where possible, but the function signatures generated by com-scrape still pass COM objects as raw pointers, and care must be taken to handle issues of ownership correctly when converting between ComPtr or ComRef and raw pointers at these boundaries.

A thorough overview of how to manage reference counts for COM objects in a variety of situations can be found on the "Rules for Managing Reference Counts" page in the Microsoft COM documentation, and the documentation for each individual ComPtr andComRef method specifies its effect on an object's reference count. However, the following rules of thumb should suffice in the majority of situations:

  1. When passing an interface pointer as a function parameter, use ComPtr::as_ptr to obtain a raw pointer from a ComPtr, or use ComRef::as_ptr to obtain a raw pointer from a ComRef.

  2. When receiving an interface pointer as the return value of a function (or via an out parameter), always use ComPtr::from_raw to obtain a ComPtr from the raw pointer.

  3. When receiving an interface pointer as a function parameter, always use ComRef::from_raw to obtain a ComRef from the raw pointer. If the received interface pointer will be stored beyond the duration of the current function, use ComRef::to_com_ptr to upgrade the ComRef to a ComPtr.

  4. When returning an interface pointer from a function (or when returning it via an out parameter), always use ComPtr::into_raw to obtain a raw pointer from a ComPtr.

Implementing COM interfaces from Rust

The Class trait can be used to define COM classes in Rust, and the ComWrapper smart pointer can be used to instantiate objects of these classes. To define a COM class, start by defining a Rust type:

struct MyClass { /* ... */ }

Then implement the desired interface traits for the type:

impl ISomeInterfaceTrait for MyClass {
    unsafe fn some_method(&self) {
        /* ... */
    }
}

impl IAnotherInterfaceTrait for MyClass {
    unsafe fn another_method(&self) {
        /* ... */
    }
}

Finally, implement the Class trait for the type, specifying the set of COM interfaces as a tuple:

impl Class for MyClass {
    type Interfaces = (ISomeInterface, IAnotherInterface);
}

With these definitions in place, ComWrapper can be used to instantiate a COM object supporting the above interfaces:

let my_obj = ComWrapper::new(MyClass);

let ptr = my_obj.to_com_ptr::<ISomeInterface>().unwrap();
ptr.some_method();

let ptr = my_obj.to_com_ptr::<IAnotherInterface>().unwrap();
ptr.another_method();

No runtime deps