#win32 #windows #com

macro derive-com-impl

Procedural macros to help implement COM interfaces from Rust

5 releases

✓ Uses Rust 2018 edition

0.1.1 Mar 1, 2019
0.1.0 Mar 1, 2019
0.1.0-alpha3 Nov 11, 2018

#47 in Windows APIs

Download history 4/week @ 2019-01-19 6/week @ 2019-01-26 1/week @ 2019-02-02 2/week @ 2019-02-09 1/week @ 2019-02-16 12/week @ 2019-02-23 80/week @ 2019-03-02 9/week @ 2019-03-09 7/week @ 2019-03-16 67/week @ 2019-03-23 12/week @ 2019-03-30 7/week @ 2019-04-06 2/week @ 2019-04-13 7/week @ 2019-04-20 9/week @ 2019-04-27

70 downloads per month
Used in 3 crates (2 directly)

MIT license

37KB
825 lines


lib.rs:

Implements a COM Object struct with automatic reference counting and implements IUnknown for you. This covers the most common use cases of creating COM objects from Rust. Supports generic parameters!

#[macro_use]
extern crate derive_com_impl;

extern crate com_impl;
extern crate winapi;
extern crate wio;

use com_impl::{VTable, Refcount};
use winapi::ctypes::c_void;
use winapi::shared::winerror::{ERROR_INVALID_INDEX, HRESULT, HRESULT_FROM_WIN32, S_OK};
use winapi::um::dwrite::{IDWriteFontFileStream, IDWriteFontFileStreamVtbl};
use wio::com::ComPtr;

#[repr(C)]
#[derive(ComImpl)]
#[interfaces(IDWriteFontFileStream)]
pub struct FileStream {
    vtbl: VTable<IDWriteFontFileStreamVtbl>,
    refcount: Refcount,
    write_time: u64,
    file_data: Vec<u8>,
}

impl FileStream {
    pub fn new(write_time: u64, data: Vec<u8>) -> ComPtr<IDWriteFontFileStream> {
        let ptr = FileStream::create_raw(write_time, data);
        let ptr = ptr as *mut IDWriteFontFileStream;
        unsafe { ComPtr::from_raw(ptr) }
    }
}

#[com_impl]
unsafe impl IDWriteFontFileStream for FileStream {
    unsafe fn get_file_size(&self, size: *mut u64) -> HRESULT {
        *size = self.file_data.len() as u64;
        S_OK
    }

    unsafe fn get_last_write_time(&self, write_time: *mut u64) -> HRESULT {
        *write_time = self.write_time;
        S_OK
    }

    unsafe fn read_file_fragment(
        &self,
        start: *mut *const c_void,
        offset: u64,
        size: u64,
        ctx: *mut *mut c_void,
    ) -> HRESULT {
        if offset > std::isize::MAX as u64 || size > std::isize::MAX as u64 {
            return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
        }

        let offset = offset as usize;
        let size = size as usize;

        if offset + size > self.file_data.len() {
            return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
        }

        *start = self.file_data.as_ptr().offset(offset as isize) as *const c_void;
        *ctx = std::ptr::null_mut();

        S_OK
    }

    unsafe fn release_file_fragment(&self, _ctx: *mut c_void) {
        // Nothing to do
    }
}

fn main() {
    let ptr = FileStream::new(100, vec![0xDE, 0xAF, 0x00, 0xF0, 0x01]);

    // Do things with ptr
}

Dependencies

~770KB
~17K SLoC