Memory 从Rust编译到Emscripten获取Javascript中的数组

Memory 从Rust编译到Emscripten获取Javascript中的数组,memory,rust,emscripten,webassembly,Memory,Rust,Emscripten,Webassembly,我想生成一个字节向量(Vec,在Rust中),并使用JS作为Array或Uint8Array访问它,然后将其发送到WebSocket或IndexedDB 我发现,这与我想做的恰恰相反,但非常相关。除此之外,我知道Emscripten中的数组类型,但不知道如何正确使用它 关于如何使其工作,我的最佳猜测是尝试将向量返回为_mut_ptr,并使用模块上的指针。HEAPU8 main.rs #[no_mangle] pub fn bytes() -> *mut u8 { vec![1, 2

我想生成一个字节向量(
Vec
,在Rust中),并使用JS作为
Array
Uint8Array
访问它,然后将其发送到WebSocket或IndexedDB

我发现,这与我想做的恰恰相反,但非常相关。除此之外,我知道Emscripten中的数组类型,但不知道如何正确使用它

关于如何使其工作,我的最佳猜测是尝试将向量
返回为_mut_ptr
,并使用
模块上的指针。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地点:11:13
UINT8阵列[0,0,0,0,0,0,0,0,0]站点:12:13
UINT8阵列[0,0,0,0,0,0,0,0,0,0,90更多…]站点:13:13
5260296地点:15:13
第一个问题是两个值都表示空数组,第二个问题是两个单独的调用指向同一内存位置。我完全不知道如何访问堆上的指向数据以及向量的长度

指向同一内存位置的两个指针可能是因为当
Vec
write的生命周期结束时,(
bytes
)函数结束时,它会生锈


抱歉,如果我错过了Wasm和Emscripten的一些基础知识,我今天只构建了我的第一个Wasm hello world。

与编写Rust相同的规则适用于这里。这意味着函数必须返回一个拥有的值;当前,它返回一个指向函数返回时删除的数据的指针

一个将返回
Vec
,它由(ptr、长度、容量)组成,太大而无法返回到C

有两种类似的解决方案:

  • 返回
    并定义另一个提取 从它的指针

  • 定义您自己的可从C访问的
    Vec


  • 我用的是后者。

    好吧,在接受了@sebk的想法之后(非常感谢你的指点)

    它实际上工作得很好,所以我将快速描述它。我们需要一个可以从JavaScript访问数组的表示,因此我们主要需要一个指针和数组的长度(在
    JsVec
    中表示)。在wasm中,您只能传递整数/浮点数,因此我们需要返回一个原始指针,
    框将
    放入到\u raw
    中,这样我们就可以返回一个指向我们的
    JsVec
    的原始指针并获取信息。为了防止锈菌掉落我们的向量,我们需要使用
    mem::forget
    忽略向量

    在javascript世界中,通过指针和
    Module.HEAPU32
    值访问堆上的数据非常简单

    下一个问题是向量的删除,因此我们使用原始指针并从中创建一个自动删除的
    ,据我所知,它会删除
    JsVec
    对象,但不会删除向量或内容。这是它可能出错的主要区域,那么这会导致内存泄漏吗?或者删除
    JsVec
    就足够了

    再次感谢你帮助我

    编辑:

    耶!我似乎已经让它工作(要点更新)。我从
    JsBytes
    (重命名)struct获取并构造了一个向量,以确保向量本身被删除


    这一点在我的浏览器中也很有效。

    我对Wasm的Javascript方面不太熟悉,对rust也不太熟悉,但我担心这两方面的专家也不多。以下是一些可能让你走上正轨的想法:1。是否需要在rust中创建阵列?可以将Javascript数组作为(可变)引用传递给rust并在那里修改它。2.您可能会在C/C++中找到更多的信息,这可能会让您了解如何在rust中执行同样的操作。“而且太大,无法返回到C”-这是不正确的,甚至没有真正意义。“返回C”的大小限制是多少?它记录在哪里?@Shepmaster Wasm只支持返回某些整数数据类型,因此在结构中返回ptr、length、capacity不起作用。感谢@sebk的响应,我接受了您在下面的回答,但我仍然需要确保它没有泄漏内存,虽然我可以从JS访问它,
    Vec
    类型已经在堆上分配,所以不需要使用
    Box
    。正确的方法是:1)使用
    收缩向量以适应()
    ,2)获取向量的长度,3)使用
    创建指针作为变量()
    ,然后4)忘记()
    原始的
    向量,以及5)传递包含指针及其长度的新结构,它可以用来在另一端重建它。@Shepmaster C允许返回一个寄存器(size\u t/usize)。通常的解决方案是传递一个指针,然后将返回数据写入该指针。这在emscripten中是可能的,但是设置起来比较复杂(需要从JS控制堆栈)。