2017-08-17 32 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訪問它。 –