如何在WebAssembly中返回对嵌套Rust结构的引用



我有两个结构,可以从JavaScript访问Parent结构,并使用new方法创建它:

struct Child {
foo: String,
}
impl Child {
pub fn do_something(&self) {
/* some stuff */
}
}
#[wasm_bindgen]
pub struct Parent {
child: Child,
}
#[wasm_bindgen]
impl Parent {
pub fn new() -> Self {
Self {
child: Child { foo: String::new() },
}
}
pub fn child(&self) -> &Child {
&self.child
}
}

由于child()方法出错,我无法编译代码

cannot return a borrowed ref with #[wasm_bindgen]

有什么方法可以获得指向child的指针并从JavaScript访问它吗?为什么Rust不能返回对WebAssembly的借用引用?这是因为JavaScript可以修改它的值,而Rust不能保证数据的不变性吗?

在WASM中,Javascript就像内核代码。它以最高级别的权限运行,并可以自由访问整个内存空间。有些人提到,如果Rust返回对JS的引用,它可能最终成为一个悬空指针。这会很糟糕,但这不是Rust的问题。与内核代码一样,Javascript也有责任在这种情况下保持安全。真正的问题是,没有办法确保JS不会滥用不可变引用来变异数据并导致内存损坏。

由于借用规则,您无法将引用从rust返回到javascript。Rust对记忆非常挑剔,不希望外界对记忆进行任何突变。然而,为了解决这个问题,我们使用了原始运算符。

您想返回child:

pub fn child(&self) -> &Child {
&self.child
}

我们在这里使用raw operator。借用规则不适用于原始运算符。

pub fn child(&self) -> *const Child {
// as_ptr is the reference to the child
&self.child.as_ptr()
} 

我们告诉编译器,我们确信,我们想要内存中这个位置的引用,我们喜欢访问引用,我们不怕借用。

原始指针是不安全的。当你在不同语言之间创建这种互操作时,它们会被大量使用。目前,您的javsacrept代码指向child引用,但如果该引用在rust代码中发生突变,那么javascript代码将指向其他内容。

最新更新