vin*_*def 7 javascript string rust webassembly
我有这个简单的Rust函数:
#[no_mangle]
pub fn compute(operator: &str, n1: i32, n2: i32) -> i32 {
match operator {
"SUM" => n1 + n2,
"DIFF" => n1 - n2,
"MULT" => n1 * n2,
"DIV" => n1 / n2,
_ => 0
}
}
Run Code Online (Sandbox Code Playgroud)
我正在成功地将其编译为WebAssembly,但是没有设法将operator
参数从JS 传递给Rust.
调用Rust函数的JS行如下所示:
instance.exports.compute(operator, n1, n2);
Run Code Online (Sandbox Code Playgroud)
operator
是JS String
和n1
,n2
是JS Number
秒.
n1
并且n2
正确传递并且可以在编译函数内部读取,所以我猜问题是我如何传递字符串.我想它是作为从JS到WebAssembly的指针传递,但无法找到有关其工作原理的证据或材料.
我没有使用Emscripten并希望将其保持独立(编译目标wasm32-unknown-unknown
),但我看到它们将其编译的函数包装起来Module.cwrap
,也许这可能会有所帮助?
She*_*ter 14
要在JavaScript和Rust之间传输字符串数据,您需要决定
我决定:
TextEncoder
JS API最适合.LIB/src.rs
[package]
name = "quick-maths"
version = "0.1.0"
authors = ["An Devloper <an.devloper@example.com>"]
[lib]
crate-type = ["cdylib"]
Run Code Online (Sandbox Code Playgroud)
为WASM构建C dylib以帮助它们缩小尺寸非常重要.
Cargo.toml
[target.wasm32-unknown-unknown]
rustflags = [
"-C", "link-args=--import-memory",
]
Run Code Online (Sandbox Code Playgroud)
对于它的价值,我在Node中运行此代码,而不是在浏览器中运行.
index.js
{
"name": "quick-maths",
"version": "0.1.0",
"main": "index.js",
"author": "An Devloper <an.devloper@example.com>",
"license": "MIT",
"scripts": {
"example": "node ./index.js"
},
"dependencies": {
"fs-extra": "^8.0.1",
"text-encoding": "^0.7.0"
}
}
Run Code Online (Sandbox Code Playgroud)
我决定:
TextEncoder
JS API最适合.Box<String>
作为底层数据结构.这允许Rust代码进一步使用分配.SRC/lib.rs
$ rustup component add rust-std --target wasm32-unknown-unknown
$ cargo build --release --target wasm32-unknown-unknown
Run Code Online (Sandbox Code Playgroud)
index.js
// A struct with a known memory layout that we can pass string information in
#[repr(C)]
pub struct JsInteropString {
data: *const u8,
len: usize,
}
// Our FFI shim function
#[no_mangle]
pub unsafe extern "C" fn compute(s: *const JsInteropString, n1: i32, n2: i32) -> i32 {
// Check for NULL (see corresponding comment in JS)
let s = match s.as_ref() {
Some(s) => s,
None => return -1,
};
// Convert the pointer and length to a `&[u8]`.
let data = std::slice::from_raw_parts(s.data, s.len);
// Convert the `&[u8]` to a `&str`
match std::str::from_utf8(data) {
Ok(s) => real_code::compute(s, n1, n2),
Err(_) => -2,
}
}
// I advocate that you keep your interesting code in a different
// crate for easy development and testing. Have a separate crate
// with the FFI shims.
mod real_code {
pub fn compute(operator: &str, n1: i32, n2: i32) -> i32 {
match operator {
"SUM" => n1 + n2,
"DIFF" => n1 - n2,
"MULT" => n1 * n2,
"DIV" => n1 / n2,
_ => 0,
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,此过程可用于其他类型.你"只是"必须决定如何将数据表示为双方同意然后发送它的一组字节.
也可以看看:
TextEncoder
APIUint8Array
/ Uint32Array
/TypedArray
WebAssembly.Memory
归档时间: |
|
查看次数: |
1541 次 |
最近记录: |