在 WASM-Bindgen Rust 中使用鼠标输入事件闭包创建回调时出现闭包调用错误

Posted

技术标签:

【中文标题】在 WASM-Bindgen Rust 中使用鼠标输入事件闭包创建回调时出现闭包调用错误【英文标题】:Clousure Invocation Error when Creating a Callback with a Clousure on Mouse Input Event in WASM-Bindgen Rust 【发布时间】:2020-12-17 18:54:09 【问题描述】:

我有一个从WASM-Bindgen "canvas" example 派生的 Rust 程序。我试图在每个 javascript onmousemove 事件上为 Canvas 元素调用一些 Rust 代码。我的代码当前成功创建了 DOM 事件(看起来)。但是,在每个触发事件时,Firefox 开发者版开发者工具的控制台都会显示错误:

Uncaught Error: closure invoked recursively or destroyed already

这是我的部分代码:

use std::f64;
use std::sync;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;

mod canvas_manager;
use canvas_manager::CanvasManager;

#[wasm_bindgen(start)]
pub fn start() 
    let document = web_sys::window().unwrap().document().unwrap();
    let canvas = document.get_element_by_id("canvas").unwrap();
    let canvas: web_sys::htmlCanvasElement = canvas
        .dyn_into::<web_sys::HtmlCanvasElement>()
        .map_err(|_| ())
        .unwrap();

    let manager = CanvasManager::new(canvas, 480, 480);

    manager.fill_rect_with_color(210, 12, 60, 6, "#444");
    
    manager.fill_rect_with_color(210, 462, 60, 6, "#444");
    
    manager.fill_rect_with_color(236, 236, 8, 8, "#999");

    manager.clear_canvas();

    let xPos= sync::Arc::from(sync::Mutex::new(Box::new(0f64)));

    let xPosCloned = xPos.clone();

    let a = Closure::wrap(Box::new(move || 
        let mut xPosBox = xPosCloned.lock().unwrap();
        **xPosBox += 1f64;
        //web_sys::console::log_1(&JsValue::from_f64(2.5f64));
    ) as Box<dyn FnMut()>);

    manager.canvas.set_onmousemove(Some(a.as_ref().unchecked_ref()));


【问题讨论】:

嗨,我是 Russ 先生 ;-)。我看到你有你的问题的答案。如果它符合您的要求,请在 Stack Overflow 上投票/接受它,如果不符合要求,则对其发表评论是一种常见的礼貌。 :-) 我相信回答者会很感激的。 :-) 【参考方案1】:

在提供的代码中,a 将被删除到 start() 的末尾。

您可以通过a.forget() 解决此问题,但随后会引入内存泄漏。

let a = Closure::wrap(Box::new(move || 
    let mut xPosBox = xPosCloned.lock().unwrap();
    **xPosBox += 1f64;
    //web_sys::console::log_1(&JsValue::from_f64(2.5f64));
) as Box<dyn FnMut()>);

manager.canvas.set_onmousemove(Some(a.as_ref().unchecked_ref()));
a.forget();

请看好answer如何避免内存泄漏。

【讨论】:

以上是关于在 WASM-Bindgen Rust 中使用鼠标输入事件闭包创建回调时出现闭包调用错误的主要内容,如果未能解决你的问题,请参考以下文章

使用 wasm-bindgen 对大型 rust 对象进行 Js 绑定

如何将嵌套 Vecs 与 wasm-bindgen 一起使用?

如何使用 Wasm-Bindgen Web_sys Wasm-pack 将字符串从 Js 传递到通过 Rust 生成的 Wasm

如何在编译为 WebAssembly 的 Rust 库中使用 C 库?

使用 Rust + WebAssembly 编写 crc32

rust用鼠标宏会不会封号