前提
C++で実装していたWin32APIを使用したWiaデバイス制御を、windows-rsを用いてRustへ置き換える作業をしています。
Rustのオブジェクト指向のような記述の知見があまりないので、C++の継承による実装を実現する手段が分からず困っています。
実現したいこと
- Wiaデバイスの接続、切断のイベントを受信する
発生している問題・エラーメッセージ
cannot construct `windows::Win32::Devices::ImageAcquisition::IWiaEventCallback` with struct literal syntax due to private fields ... and other private field `0` that was not providedrustcClick for full compiler diagnostic
該当のソースコード
RegisterEventCallbackInterfaceの第四引数に渡すところでエラーが発生しています。(70行目)
13行目からのFromトレイトを実装することで継承のようなことが実現できるという認識ですが、実現方法が分かりません。
Rust
1use std::mem::ManuallyDrop; 2use std::ptr; 3 4use windows::{ 5 core::*, 6 Win32::{Devices::ImageAcquisition::*, System::Com::StructuredStorage::*, System::Com::*}, 7}; 8 9pub struct Wia { 10 mgr: IWiaDevMgr, 11} 12 13impl From<Wia> for IWiaEventCallback { 14 fn from(val: Wia) -> Self { 15 Self { 16 // ★? 17 } 18 } 19} 20 21impl Wia { 22 pub unsafe fn init() -> Self { 23 CoInitialize(None).unwrap(); 24 25 let mgr = CoCreateInstance(&WiaDevMgr, None, CLSCTX_LOCAL_SERVER).unwrap(); 26 27 Self { mgr: mgr } 28 } 29 30 pub fn ImageEventCallback( 31 &self, 32 peventguid: *const GUID, 33 bstreventdescription: &BSTR, 34 bstrdeviceid: &BSTR, 35 bstrdevicedescription: &BSTR, 36 dwdevicetype: u32, 37 bstrfullitemname: &BSTR, 38 puleventtype: *mut u32, 39 ulreserved: u32, 40 ) -> Result<()> { 41 Ok(()) 42 } 43 44 pub unsafe fn try_connect(&mut self) -> Result<()> { 45 let enum_info = self.mgr.EnumDeviceInfo(WIA_DEVINFO_ENUM_LOCAL as i32)?; 46 println!("try_connect {:?}", enum_info.GetCount()?); 47 48 let mut opt: Option<IWiaPropertyStorage> = Default::default(); 49 enum_info.Next( 50 1, 51 &mut opt as *mut Option<IWiaPropertyStorage>, 52 ptr::null_mut(), 53 )?; 54 let storage = opt.unwrap(); 55 56 let mut var = storage 57 .ReadMultiple( 58 1, 59 &PROPSPEC { 60 ulKind: PRSPEC_PROPID, 61 Anonymous: PROPSPEC_0 { 62 propid: WIA_DIP_DEV_ID, 63 }, 64 }, 65 )? 66 .Anonymous 67 .Anonymous; 68 69 self.mgr 70 .RegisterEventCallbackInterface::<IWiaEventCallback>( 71 0, 72 &var.Anonymous.bstrVal, 73 &WIA_EVENT_DEVICE_DISCONNECTED, 74 &self.into(), // ★? 75 ); 76 77 ManuallyDrop::drop(&mut var.Anonymous.bstrVal); 78 79 Ok(()) 80 } 81}
また、C++では以下のような実装で実現できていました。(一部抜粋)
cpp
1// .h 2class CWia : public IWiaEventCallback 3{ 4public: 5 STDMETHOD_(HRESULT __stdcall, QueryInterface)(REFIID iid, LPVOID* ppvObj); 6 STDMETHOD_(ULONG __stdcall, AddRef)(); 7 STDMETHOD_(ULONG __stdcall, Release)(); 8 9 STDMETHOD_(HRESULT __stdcall, ImageEventCallback)( 10 LPCGUID pEventGuid, 11 BSTR bstrEventDescription, 12 BSTR bstrDeviceID, 13 BSTR bstrDeviceDescription, 14 DWORD dwDeviceType, 15 BSTR bstrFullItemName, 16 ULONG* pulEventType, 17 ULONG ulReserved 18 ); 19 20 HRESULT Register(); 21 22private: 23 CComPtr<IWiaDevMgr> m_pWiaDevMgr; 24 25 LONG m_cRef; 26 27 CComPtr<IUnknown> m_pConnectEventObject; 28 CComPtr<IUnknown> m_pDisconnectEventObject; 29} 30 31// .c 32STDMETHODIMP CWia::ImageEventCallback( 33 LPCGUID pEventGuid, 34 BSTR bstrEventDescription, 35 BSTR bstrDeviceID, 36 BSTR bstrDeviceDescription, 37 DWORD dwDeviceType, 38 BSTR bstrFullItemName, 39 ULONG* pulEventType, 40 ULONG ulReserved 41) { 42 if (*pEventGuid == WIA_EVENT_DEVICE_CONNECTED) 43 { 44 // connected 45 } 46 else if (*pEventGuid == WIA_EVENT_DEVICE_DISCONNECTED) 47 { 48 // disconnected 49 } 50 51 return S_OK; 52} 53 54HRESULT CWia::Register() 55{ 56 HRESULT hr; 57 58 hr = m_pWiaDevMgr->RegisterEventCallbackInterface( 59 0, 60 nullptr, 61 &WIA_EVENT_DEVICE_CONNECTED, 62 this, 63 &m_pConnectEventObject 64 ); 65 if (FAILED(hr)) 66 { 67 return hr; 68 } 69 70 hr = m_pWiaDevMgr->RegisterEventCallbackInterface( 71 0, 72 nullptr, 73 &WIA_EVENT_DEVICE_DISCONNECTED, 74 this, 75 &m_pDisconnectEventObject 76 ); 77 if (FAILED(hr)) 78 { 79 return hr; 80 } 81 82 return S_OK; 83} 84
補足情報(FW/ツールのバージョンなど)
windows-rs 0.43
あなたの回答
tips
プレビュー