質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

0回答

645閲覧

windows-rsを使用したコールバックの受信方法

choro0121

総合スコア1

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

0クリップ

投稿2022/12/19 00:53

前提

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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問