从编译为 Emscripten 的 Rust 获取 Javascript 中的数组
Getting an array in Javascript from Rust compiled to Emscripten
我想生成一个字节向量(Vec<u8>
在 Rust 中)并使用 JS 作为 Array
或 Uint8Array
访问它并将它发送到 WebSocket 或 IndexedDB。
我发现 How can I pass an array from JavaScript to Rust that has been compiled with Emscripten?,这与我想做的完全相反,但非常相关。除此之外,我知道 Emscripten 中的数组类型,但我不知道如何正确使用它。
我最好的猜测是尝试返回向量 as_mut_ptr
,并使用 Module.HEAPU8
上的指针。
main.rs
#[no_mangle]
pub fn bytes() -> *mut u8 {
vec![1, 2, 3].as_mut_ptr()
}
fn main() {}
index.html
的一部分
var Module = {
wasmBinaryFile: "site.wasm",
onRuntimeInitialized: main,
};
function main() {
let ptr = Module._bytes();
console.log(ptr);
console.log(Module.HEAPU8.slice(ptr, ptr + 10));
console.log(Module.HEAPU8.subarray(ptr, ptr + 100));
let arr = Module.cwrap('bytes', 'array', []);
console.log(arr());
}
控制台的结果最终如下所示:
5260296 site:11:13
Uint8Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] site:12:13
Uint8Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90 more… ] site:13:13
5260296 site:15:13
第一个问题是两个值都表示空数组,第二个问题是两个单独的调用指向相同的内存位置。我完全不知道如何访问堆上指向的数据以及向量的长度。
指向同一内存位置的两个指针可能是因为 Rust 在其生命周期结束时丢弃 Vec<u8>
写入,(bytes
函数结束)。
抱歉,如果我错过了 Wasm 和 Emscripten 的一些基础知识,我今天才构建了我的第一个 Wasm hello world。
此处适用与编写 Rust 相同的规则。这意味着该函数必须 return 一个拥有的值;目前它 returns 是一个指向数据的指针,当函数 returns.
一个会 return Vec<u8>
由 (ptr, length, capacity) 组成并且太大以至于 return 到 C.
有两个类似的解决方案:
return Box<Vec<u8>>
并定义另一个函数来提取
来自它的指针。
定义您自己的 Vec
可从 C 访问。
我用的是后者here.
好的,所以在从@sebk 那里得到想法之后(非常感谢您的指点)。 This is what I came up with.
它实际上很好用,所以我将快速描述它。我们需要一个可以从 javacript 访问数组的表示,所以我们主要需要一个指针和数组的长度(在 JsVec
中表示)。在 wasm 中你只能传递 integers/floats,所以我们需要 return 一个原始指针,Box
有 into_raw
所以我们可以 return 一个指向我们的原始指针JsVec
并获取信息。为了防止 Rust 丢弃我们的向量,我们需要忘记向量,使用 mem::forget
.
在javascript 世界中,它就像通过指针和Module.HEAPU32
值访问堆上的数据一样简单。
下一个问题是 vector 的删除,所以我们使用原始指针并从中创建一个 Box
,它会自动删除,据我所知,它会删除 JsVec
对象,但是不是 vec 或内容。这是它可能出错的主要区域,所以这会导致内存泄漏吗?或者删除 JsVec
就足够了。
再次感谢您帮助我。
编辑:
耶!我似乎已经让它工作了(要点已更新)。我采用 this reddit comment's advice 并从 JsBytes
(重命名)结构构建了一个向量,以确保向量本身被删除!
这有效,要点在我的浏览器中有效。
我想生成一个字节向量(Vec<u8>
在 Rust 中)并使用 JS 作为 Array
或 Uint8Array
访问它并将它发送到 WebSocket 或 IndexedDB。
我发现 How can I pass an array from JavaScript to Rust that has been compiled with Emscripten?,这与我想做的完全相反,但非常相关。除此之外,我知道 Emscripten 中的数组类型,但我不知道如何正确使用它。
我最好的猜测是尝试返回向量 as_mut_ptr
,并使用 Module.HEAPU8
上的指针。
main.rs
#[no_mangle]
pub fn bytes() -> *mut u8 {
vec![1, 2, 3].as_mut_ptr()
}
fn main() {}
index.html
的一部分var Module = {
wasmBinaryFile: "site.wasm",
onRuntimeInitialized: main,
};
function main() {
let ptr = Module._bytes();
console.log(ptr);
console.log(Module.HEAPU8.slice(ptr, ptr + 10));
console.log(Module.HEAPU8.subarray(ptr, ptr + 100));
let arr = Module.cwrap('bytes', 'array', []);
console.log(arr());
}
控制台的结果最终如下所示:
5260296 site:11:13
Uint8Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] site:12:13
Uint8Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90 more… ] site:13:13
5260296 site:15:13
第一个问题是两个值都表示空数组,第二个问题是两个单独的调用指向相同的内存位置。我完全不知道如何访问堆上指向的数据以及向量的长度。
指向同一内存位置的两个指针可能是因为 Rust 在其生命周期结束时丢弃 Vec<u8>
写入,(bytes
函数结束)。
抱歉,如果我错过了 Wasm 和 Emscripten 的一些基础知识,我今天才构建了我的第一个 Wasm hello world。
此处适用与编写 Rust 相同的规则。这意味着该函数必须 return 一个拥有的值;目前它 returns 是一个指向数据的指针,当函数 returns.
一个会 return Vec<u8>
由 (ptr, length, capacity) 组成并且太大以至于 return 到 C.
有两个类似的解决方案:
return
Box<Vec<u8>>
并定义另一个函数来提取 来自它的指针。定义您自己的
Vec
可从 C 访问。
我用的是后者here.
好的,所以在从@sebk 那里得到想法之后(非常感谢您的指点)。 This is what I came up with.
它实际上很好用,所以我将快速描述它。我们需要一个可以从 javacript 访问数组的表示,所以我们主要需要一个指针和数组的长度(在 JsVec
中表示)。在 wasm 中你只能传递 integers/floats,所以我们需要 return 一个原始指针,Box
有 into_raw
所以我们可以 return 一个指向我们的原始指针JsVec
并获取信息。为了防止 Rust 丢弃我们的向量,我们需要忘记向量,使用 mem::forget
.
在javascript 世界中,它就像通过指针和Module.HEAPU32
值访问堆上的数据一样简单。
下一个问题是 vector 的删除,所以我们使用原始指针并从中创建一个 Box
,它会自动删除,据我所知,它会删除 JsVec
对象,但是不是 vec 或内容。这是它可能出错的主要区域,所以这会导致内存泄漏吗?或者删除 JsVec
就足够了。
再次感谢您帮助我。
编辑:
耶!我似乎已经让它工作了(要点已更新)。我采用 this reddit comment's advice 并从 JsBytes
(重命名)结构构建了一个向量,以确保向量本身被删除!
这有效,要点在我的浏览器中有效。