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

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

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

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

Rust

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

Q&A

解決済

2回答

1285閲覧

Rust: [E0434]can't capture dynamic environment in a fn itemが出て実行できない

lattex

総合スコア4

Win32 API

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

Rust

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

0グッド

0クリップ

投稿2022/03/30 23:13

前提

Rust言語でGUIライブラリを作っています。
Windows側の処理でApplicationトレイト内のメソッドをウィンドウプロシージャの中で呼び出そうとしたところ、以下のエラーが発生しました

発生している問題・エラーメッセージ

error[E0434]: can't capture dynamic environment in a fn item --> nxui\src\nxui.rs:48:21 | 48 | application.exit(); | ^^^^^^^^^^^ | = help: use the `|| { ... }` closure form instead

該当のソースコード

Rust

1fn create_new_app(application: Box<dyn Application>) { 2 // Get window title 3 let app_name = application.app_name(); 4 // Get attributes 5 let attributes = application.attributes(); 6 let storage = Storage::new(get_app_dirs(app_name)); 7 let advanced_option = application.advanced_options(); 8 // startup process 9 if application.is_child_window() == false { 10 storage.create_app_dir(); 11 } 12 application.startup(storage); 13 14 // Create a window 15 use windows_sys::{ 16 Win32::Foundation::*, Win32::System::LibraryLoader::GetModuleHandleA, 17 Win32::UI::WindowsAndMessaging::*, 18 }; 19 extern "system" fn wndproc( 20 window: HWND, 21 message: u32, 22 wparam: WPARAM, 23 lparam: LPARAM, 24 ) -> LRESULT { 25 unsafe{ 26 match message as u32 { 27 WM_DESTROY => { 28 println!("WM_DESTROY"); 29 PostQuitMessage(0); 30 0 31 } 32 33 WM_CREATE => { 34 0 35 } 36 37 WM_CLOSE => { 38 info!("Exit Phase"); 39 application.exit(); 40 0 41 } 42 43 _ => DefWindowProcA(window, message, wparam, lparam), 44 } 45 } 46 } 47 48 unsafe { 49 let instance = GetModuleHandleA(std::ptr::null_mut()); 50 debug_assert!(instance != 0); 51 use windows_sys::Win32::Graphics::Gdi::HBRUSH; 52 let wc = WNDCLASSA { 53 hCursor: LoadCursorW(0, IDC_ARROW), 54 hInstance: instance, 55 lpszClassName: "window".as_ptr(), 56 style: CS_HREDRAW | CS_VREDRAW, 57 lpfnWndProc: Some(wndproc), 58 cbClsExtra: 0, 59 cbWndExtra: 0, 60 hIcon: 0, 61 hbrBackground: advanced_option.get_background_color() as HBRUSH, 62 lpszMenuName: std::ptr::null_mut(), 63 }; 64 65 let atom = RegisterClassA(&wc); 66 debug_assert!(atom != 0); 67 let win = CreateWindowExA( 68 advanced_option.get_style(), 69 b"window".as_ptr(), 70 format!("{}\0", attributes.title).as_ptr(), 71 attributes.style | WS_VISIBLE, 72 attributes.x, 73 attributes.y, 74 attributes.width, 75 attributes.height, 76 0, 77 0, 78 instance, 79 std::ptr::null_mut(), 80 ); 81 if win == 0 { 82 panic!("Window could not be initialized"); 83 } 84 85 info!("A window has been created. handle: {}", win); 86 87 let frame = Frame::new(win); 88 info!("Frame has been created."); 89 info!("UI Phase"); 90 application.ui(&frame); 91 92 let mut message = std::mem::zeroed(); 93 94 while GetMessageA(&mut message, 0, 0, 0) != 0 { 95 TranslateMessage(&message); 96 DispatchMessageA(&message); 97 } 98 } 99}

Rust

1pub trait Application { 2 /// Returns the name of the application. 3 fn app_name(&self) -> String; 4 /// Returns WindowAttributes. 5 fn attributes(&self) -> Attributes; 6 7 fn is_child_window(&self) -> bool; 8 9 fn advanced_options(&self) -> AdvancedOptions { 10 AdvancedOptions::default() 11 } 12 13 /// Processing at application startup (optional) 14 fn startup(&self, _storage: Storage) {} 15 16 /// Writing UI processes and events 17 fn ui(&self, frame: &Frame); 18 /// Processing at application termination (optional) 19 fn exit(&self) {} 20}

どなたか解決方法を教えていただけないでしょうか

補足情報(FW/ツールのバージョンなど)

  • Rustc 1.57
  • windows-sys 0.34.0

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

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

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

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

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

guest

回答2

0

ベストアンサー

関数の中で関数を定義する場合、定義しようとする関数は関数の外で定義するのと同じです。 スコープが違うだけです。 ですから、 create_new_app のローカル変数である application をキャプチャすることは出来ません。

CreateWindowExAlpparamapplication を渡し、ウィンドウプロシージャでは受け取った情報を SetPropA でウィンドウハンドルに対応付けて記録し、必要に応じて GetPropAで取り出すのが常道だろうと思います。

投稿2022/03/31 07:35

SaitoAtsushi

総合スコア5446

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

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

lattex

2022/04/01 10:22

とても勉強になりました。皆さんありがとうございました!
guest

0

application.exit()wndproc()関数のなかで呼び出されていますが、同関数の中でapplicationは宣言されていないので使えません。

エラーメッセージは、関数ではなくクロージャならcreate_new_app()の引数のapplicationをキャプチャして使用できる、ということを言っています。ただ、wndproc()関数はあとでWNDCLASSAで使うため関数でないといけません。

ここからは蛇足&私もあまり詳しくないのですが、ではapplicationをどうやってwndproc()内で使うかという件については、CreateWindowExA()の最後の引数にポインタにしたapplicationを渡すのに加えSetWindowLongPtr()GetWindowLongPtr()を使うのが定石のようです。

windowsクレートのサンプルが下記にあります。create_window, create_window_sys はwndproc()のシンプルな例として、direct2dはapplicationwndproc()で使う例として参考になると思います。
https://github.com/microsoft/windows-rs/tree/master/crates/samples

Microsoftのwin32apiの解説のページ(C++)
https://docs.microsoft.com/ja-jp/windows/win32/learnwin32/managing-application-state-

投稿2022/03/31 07:33

編集2022/03/31 07:39
KoyaMaan

総合スコア6

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問