【发布时间】:2021-04-23 00:13:23
【问题描述】:
我一直在尝试将字符串传递给 Rust 函数(编译为 Wasm),但是据我了解,目前无法直接传递字符串,因为“str”不是“ FFI 世界”(至少 rust 编译器是这么说的):
= help: consider using `*const u8` and a length instead
所以我所做的就是将函数更改为这种形式(而不是使用简单的 &str 类型):
#[no_mangle]
pub extern "C" fn greet(s: *mut u8, len: usize) {
let s = std::str::from_utf8(unsafe { std::slice::from_raw_parts(s, len) }).unwrap();
println!("Hello, {}!", s)
}
这意味着我需要一个指针和u8中字符串的长度。
但是,有人让我注意到 WASM 模块是沙盒的,因此它们不能像普通应用程序那样使用普通指针。因此,我必须使用这样的函数将内存分配到模块的线性内存中:
use std::alloc::{alloc, dealloc, Layout};
#[no_mangle]
pub unsafe fn my_alloc(len: usize) -> *mut u8 {
let align = std::mem::align_of::<usize>();
let layout = Layout::from_size_align_unchecked(size, align);
alloc(layout)
}
这是一个 JS 函数的示例,它使用了这样的 alloc 函数:
function copyMemory(data, instance) {
var ptr = instance.exports.alloc(data.length);
var mem = new Uint8Array(instance.exports.memory.buffer, ptr, data.length);
mem.set(new Uint8Array(data));
return ptr;
}
我的问题是我不知道如何将此函数转换为 Go,那是因为我卡在“var mem”行,原因如下:
- 我在 Go 中找不到“instance.exports.memory.buffer”的等效项(实例是“*wasmtime.Instance”类型)。
- 我不知道 Unit8Buffer 在 Go 中的作用。
关于 Wasm 内存的好读物:(https://radu-matei.com/blog/practical-guide-to-wasm-memory/#exchanging-strings-between-modules-and-runtimes)
【问题讨论】:
-
不确定我是否理解你的问题,但我会说指向切片的指针与指向切片第一个元素的指针不同(就像数组一样)
-
@HymnsForDisco,如果我不清楚,我很抱歉。我会尽量让它更容易理解。谢谢你的回答。
-
您可以使用
&s[0]来获取指向切片的第一个元素的指针(切片是连续的内存,因此只要您传递正确的len,就应该是安全的)。虽然我不是 wasmtime 用户,所以我不知道这是否会实现你的最终目标,但这是我的 2 美分。 -
老实说,我迷路了,一切都有帮助。谢谢
标签: go rust webassembly rust-wasm wasmtime