在 Windows 窗口回调中获取某种静态引用

问题描述 投票:0回答:1

我对 Rust 编程有点陌生。在过去的两个月里我学到了很多东西,但目前我可以使用一些有根据的建议。

过去,我一直遵循 C++ 教程系列来使用 DirectX11 构建引擎(参见此)到了一定程度。了解 Rust 后,我决定将项目转移到 Rust,并在此过程中了解更多信息。

所以我想重现的是,教程将指向窗口类的指针插入到窗口回调中的方式。我通过实施成功实现了它

// inside 'impl BEWindow'
extern "system" fn initialize_proc(window:HWND, message: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT {
        unsafe {
            if message == WM_CREATE {
                let pCreate = *(lparam.0 as *const c_void as *const CREATESTRUCTA);
                let wnd = pCreate.lpCreateParams as *mut BEWindow;
                SetWindowLongPtrW(window, GWLP_USERDATA, *(wnd as *mut isize));
                SetWindowLongPtrW(window, GWLP_WNDPROC, BEWindow::run_proc as *const c_void as isize);
                let ret =wnd.as_ref().unwrap().handle_message(window, message, wparam, lparam);
                return ret
   }
}

extern "system" fn run_proc(window:HWND, message:u32, wparam: WPARAM, lparam: LPARAM) ->LRESULT {
        unsafe {
            if let Some(optional_wnd) = &GLOBAL_WND {
                let mut wnd = optional_wnd.lock().unwrap();
                return wnd.handle_message(window, message, wparam, lparam)
            }
            else {
                LRESULT(0)
            }
        }
    }

这种短期有效。在回调的前几次迭代之后,引用的结构发生了移动,并且我收到了分段错误,因为用户数据中的指针未更新。

经过一些研究,我发现 Arc 和 Mutex 看起来有点适合我的问题。据我理解本教程,“外部“系统”回调”应该由窗口线程执行。

我想知道我是否需要initialize_proc将指针放入UserData中,当我也可以使用静态时。

static mut GLOBAL_WND: Option<Arc<Mutex<BEWindow>>> = None;

//struct BEWindow
impl BEWindow{
   //other functions
   // new function sets the value of GLOBAL_WND to Some( ... arc ...) and returns a cloned 
   // version of the arc, it also creates the window with the winapi 
   extern "system" fn run_proc(window:HWND, message:u32, wparam: WPARAM, lparam: LPARAM) ->LRESULT {
        unsafe {
            if let Some(optional_wnd) = &GLOBAL_WND {
                let mut wnd = optional_wnd.lock().unwrap();
                return wnd.handle_message(window, message, wparam, lparam)
            }
            else {
                LRESULT(0)
            }
        }
    }

}

这似乎不起作用。静态永远不会真正更新。调试时:在回调中,静态似乎始终为 None。

所以我认为我对 Rust 中的静态以及它们在多线程中的行为方式缺乏一些了解。 它也可能与我的新函数中的操作顺序有关。 (我现在还没有一个最小的例子)

我愿意接受代码的某些替代结构。我真正想通过获取指针来实现的是过滤从窗口获得的消息,将它们放入一些队列中,并从主线程中的游戏循环访问它们。 我认为这可以通过一些不太复杂的代码来实现。

winapi rust
1个回答
0
投票

@IInspectable 的评论让我走上了正确的道路。

win-win 板条箱是如何使用 Rc 将结构注入窗口过程的一个很好的示例。

很棒的发现!

© www.soinside.com 2019 - 2024. All rights reserved.