rust - 使用 wasm-bindgen 时,如何解决无法导出具有生命周期的函数的问题?
问题描述
我正在尝试编写一个在浏览器中运行的简单游戏,考虑到浏览器、rust 和 wasm-bindgen 施加的限制组合,我很难对游戏循环进行建模。
浏览器中的典型游戏循环遵循以下一般模式:
function mainLoop() {
update();
draw();
requestAnimationFrame(mainLoop);
}
如果我要在 rust/wasm-bindgen 中模拟这个精确的模式,它看起来像这样:
let main_loop = Closure::wrap(Box::new(move || {
update();
draw();
window.request_animation_frame(main_loop.as_ref().unchecked_ref()); // Not legal
}) as Box<FnMut()>);
与 javascript 不同,我无法main_loop
从自身内部引用,所以这不起作用。
有人建议的另一种方法是遵循生命游戏示例中说明的模式。在高层次上,它涉及导出一个包含游戏状态的类型,并包括可以从 javascript 游戏循环中调用的公共tick()
和函数。render()
这对我不起作用,因为我的游戏状态需要生命周期参数,因为它实际上只是包装了规范 World
和Dispatcher
结构,后者具有生命周期参数。最终,这意味着我无法使用#[wasm_bindgen]
.
我很难找到解决这些限制的方法,并且正在寻找建议。
解决方案
对此建模的最简单方法可能是将调用留给requestAnimationFrame
JS,而只是在 Rust 中实现更新/绘制逻辑。
然而,在 Rust 中,您还可以利用这样一个事实,即实际上不捕获任何变量的闭包大小为零,这意味着Closure<T>
该闭包不会分配内存,您可以放心地忘记它。例如,这样的事情应该可以工作:
#[wasm_bindgen]
pub fn main_loop() {
update();
draw();
let window = ...;
let closure = Closure::wrap(Box::new(|| main_loop()) as Box<Fn()>);
window.request_animation_frame(closure.as_ref().unchecked_ref());
closure.forget(); // not actually leaking memory
}
如果您的状态在其中包含生命周期,那么不幸的是,这与返回 JS 不兼容,因为当您一直返回到 JS 事件循环时,所有 WebAssembly 堆栈帧都已弹出,这意味着任何生命周期都无效。这意味着您的游戏状态在main_loop
需要的迭代中持续存在'static
推荐阅读
- android - Android 导航组件 - 在整个应用生命周期中存储/访问数据
- java - 我想知道如何创建一个包含多个包的 jar 文件
- mysql - 如何为laravel中的管理员进行自定义登录?
- python - AttributeError:无法获取属性“InsertNews”
我正在尝试编写一个程序来抓取网站内容。该脚本似乎运行了一段时间,但在几次迭代后停止
Traceback (most recent call last): File "D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\lib\mult
- python - 如何发布位于包含 git lfs 文件的 git 存储库中的 Python 包?
- c# - 在将数据保存到多个表时无法跟踪实体类型的实例
- typescript - 在 TypeScript 中描述输入类型的联合
- mysql - 如何在MYSQL中查找子表中不存在的记录?
- vue.js - 当我使用社交分享包时,如何在 vue js 中的社交媒体上分享二维码图像
- arrays - 在C中添加数组的指针