如何从 Go 中调用 Rust 函数,并使用字符串作为参数?

我一直在尝试将字符串传递给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 函数的示例,它使用如下的分配函数:


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.实例“类型)。

我不知道如何做Unit8Buffer在Go中所做的。

关于Wasm中记忆的好读:(https://radu-matei.com/blog/practical-guide-to-wasm-memory/#exchanging-strings-between-modules-and-runtimes)


梦里花落0921
浏览 178回答 1
1回答

UYOU

我花了一点时间来确切地理解wasmtime Go-package是如何工作的,但最终我解决了我这样做的问题:func main() {&nbsp; &nbsp; dir, err := ioutil.TempDir("", "out")&nbsp; &nbsp; check(err)&nbsp; &nbsp; defer os.RemoveAll(dir)&nbsp; &nbsp; stdoutPath := filepath.Join(dir, "stdout")&nbsp; &nbsp; engine := wasmtime.NewEngine()&nbsp; &nbsp; store := wasmtime.NewStore(engine)&nbsp; &nbsp; linker := wasmtime.NewLinker(store)&nbsp; &nbsp; // Configure WASI imports to write stdout into a file.&nbsp; &nbsp; wasiConfig := wasmtime.NewWasiConfig()&nbsp; &nbsp; wasiConfig.SetStdoutFile(stdoutPath)&nbsp; &nbsp; wasi, err := wasmtime.NewWasiInstance(store, wasiConfig, "wasi_snapshot_preview1")&nbsp; &nbsp; check(err)&nbsp; &nbsp; // Link WASI&nbsp; &nbsp; err = linker.DefineWasi(wasi)&nbsp; &nbsp; check(err)&nbsp; &nbsp; // Create our module&nbsp; &nbsp; module, err := wasmtime.NewModuleFromFile(store.Engine, "wasm_file.wasm")&nbsp; &nbsp; check(err)&nbsp; &nbsp; instance, err := linker.Instantiate(module)&nbsp; &nbsp; check(err)&nbsp; &nbsp; fn := instance.GetExport("greet").Func()&nbsp; &nbsp; memory := instance.GetExport("memory").Memory()&nbsp; &nbsp; alloc := instance.GetExport("my_alloc").Func()&nbsp; &nbsp; // // string for alloc&nbsp; &nbsp; size2 := int32(len([]byte("Elvis")))&nbsp; &nbsp; // //Allocate memomory&nbsp; &nbsp; ptr2, err := alloc.Call(size2)&nbsp; &nbsp; pointer, _ := ptr2.(int32)&nbsp; &nbsp; buf := memory.UnsafeData()&nbsp; &nbsp; for i, v := range []byte("Elvis") {&nbsp; &nbsp; &nbsp; &nbsp; buf[pointer+int32(i)] = v&nbsp; &nbsp; }&nbsp; &nbsp; // Use string func&nbsp; &nbsp; _, err = fn.Call(pointer, size2 )&nbsp; &nbsp; check(err)&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; // Print WASM stdout&nbsp; &nbsp; out, err := ioutil.ReadFile(stdoutPath)&nbsp; &nbsp; check(err)&nbsp; &nbsp; fmt.Print(string(out))}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go