COM is implemented as flat vtable structs. For example,
interface A {
HRESULT DoSomethingA([in] UINT value);
}
interface B: A {
HRESULT DoSomethingB([in] UINT value);
}
becomes (in C)
struct AVtbl {
// A methods
HRESULT (STDMETHODCALLTYPE *DoSomethingA)(A* This, UINT value);
};
struct A { AVtbl* vtable; };
struct BVtbl {
// A methods (inherited)
HRESULT (STDMETHODCALLTYPE *DoSomethingA)(B* This, UINT value);
// B methods
HRESULT (STDMETHODCALLTYPE *DoSomethingB)(B* This, UINT value);
};
struct B { BVtbl * vtable; };
That is, "inheritance" on COM interfaces are flatten down in C/C++ world (struct B does not inherit struct A but instead struct B copies all methods from struct A), and since COM uses simple C++ vtable ABI, it's straightforward to use COM in C (AVtbl/BVtbl).
So it's possible to generate "good" COM bindings. e.g.
struct BVtbl {
DoSomethingA: extern "stdcall" fn(This: *mut B, value: UINT) -> HRESULT;
DoSomethingB: extern "stdcall" fn(This: *mut B, value: UINT) -> HRESULT;
};
struct B { vtable: *const BVtbl; };
impl B {
fn DoSomethingA(&mut self, value: UINT) -> HRESULT {
unsafe { (self.vtable.DoSomethingA)(self, value) }
}
fn DoSomethingB(&mut self, value: UINT) -> HRESULT {
unsafe { (self.vtable.DoSomethingB)(self, value) }
}
}
then some_b.DoSomethingA(value); is possible and it looks good. See proof-of-concept demo.
mingw-w64 maintains .idl files (e.g. shobjidl.idl) as well as corresponding C headers (e.g. shobjidl.h). This means we may use rust-bindgen to generate COM binding from C header, although the "raw binding" may not be convenient.
It's also possible to create COM bindings by hands. Some months ago I've created a some COM bindings by hands, but it's definitely not feasible.
It's also possible to write a MIDL-to-rust binding generator. I think it's the best way, but currently I don't know how hard it is.. :P
COM is implemented as flat vtable structs. For example,
becomes (in C)
That is, "inheritance" on COM interfaces are flatten down in C/C++ world (
struct Bdoes not inheritstruct Abut insteadstruct Bcopies all methods fromstruct A), and since COM uses simple C++ vtable ABI, it's straightforward to use COM in C (AVtbl/BVtbl).So it's possible to generate "good" COM bindings. e.g.
then
some_b.DoSomethingA(value);is possible and it looks good. See proof-of-concept demo.mingw-w64 maintains
.idlfiles (e.g. shobjidl.idl) as well as corresponding C headers (e.g. shobjidl.h). This means we may use rust-bindgen to generate COM binding from C header, although the "raw binding" may not be convenient.It's also possible to create COM bindings by hands. Some months ago I've created a some COM bindings by hands, but it's definitely not feasible.
It's also possible to write a MIDL-to-rust binding generator. I think it's the best way, but currently I don't know how hard it is.. :P