我有两个结构,可以从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代码将指向其他内容。