#derive #com #impl #macros

macro derive-com-impl

Procedural macros to help implement COM interfaces from Rust

2 releases

0.1.0-alpha2 Nov 11, 2018
Download history 43/week @ 2018-11-16 4/week @ 2018-11-23 13/week @ 2018-11-30 10/week @ 2018-12-07

4 downloads per month

MIT license

825 lines


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!

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;

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) }

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

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

    unsafe fn read_file_fragment(
        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 {

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

        if offset + size > self.file_data.len() {

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


    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


~19K SLoC