2017-08-17 95 views
4

我想生成一个向量字节(Vec<u8> Rust),并用JS作为ArrayUint8Array访问它,并将它发送到WebSocket或IndexedDB。从Rust编译成Emscripten在JavaScript中获得一个数组

我发现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在生命周期结束时(bytes的末尾)写入Vec<u8>函数。

对不起,如果我错过了Wasm和Emscripten的一些基本知识,我今天只建立了我的第一个Wasm hello world。

+0

我对Wasm的Javascript方面并不熟悉,也不太熟悉生锈,但恐怕在这里也没有太多的专家。以下是一些可能会让你走上正轨的想法:1.你需要创建一个防锈的阵列吗?它可能会传递一个Javascript数组作为(可变)引用来生锈并在那里修改它。 2.您可以在C/C++中找到更多信息,这可能会让您知道如何在C/C++中执行相同操作。 – kazemakase

回答

0

好吧,所以在从@sebk采取了想法(感谢一吨的指针)。 This is what I came up with.

它实际上运行良好,所以我会尽快描述它。我们需要一个表示,我们可以从javacript访问数组,所以主要我们需要一个指针和数组的长度(在JsVec中表示)。在wasm中,你只能传递整数/浮点数,所以我们需要返回一个原始指针,Boxinto_raw,所以我们可以返回一个原始指针到我们的JsVec并获取信息。为了防止Rust丢弃我们的矢量,我们需要使用mem::forget来忘记矢量。

在javascript环境中,它非常简单,只需通过指针和Module.HEAPU32值访问堆上的数据即可。

下一个问题是矢量的丢失,所以我们使用原始指针并从中创建一个Box,它会自动丢弃,根据我的理解,它将丢弃JsVec对象,但不包含vec或内容。这是可能出错的主要区域,这是否会导致内存泄漏?或者会丢掉JsVec就足够了。

再次感谢您的帮助。

编辑:

耶!我似乎已经得到它的工作(要点更新)。我拿了this reddit comment's advice并构建了一个从JsBytes(重命名)结构的向量,以确保向量本身被删除!

这个作品和主要作品在我的浏览器。

1

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

一个将返回Vec<u8>它由(PTR,长度,容量)和太大而无法返回C.

有两个类似的解决方案,以这样的:

  1. 回报Box<Vec<u8>>和定义另一个功能是从中提取指针 。

  2. 定义自己的Vec是从C

我使用的是后者here访问。

+0

“太大而无法返回C” - 这是不正确的,甚至没有意义。什么是“返回到C”的大小限制以及它在哪里记录? – Shepmaster

+0

@Shepmaster Wasm仅支持返回某些整型数据类型,因此返回结构中的ptr,length和capacity不起作用。 –

+0

感谢回复@sebk,我在下面回答了你的回答,但是我仍然需要确保它没有泄漏内存,尽管我可以从JS访问它。 –