登录
首页 >  Golang >  Go问答

Go 如何调用 Rust 函数并传递字符串参数?

来源:stackoverflow

时间:2024-02-23 18:00:27 225浏览 收藏

小伙伴们有没有觉得学习Golang很有意思?有意思就对了!今天就给大家带来《Go 如何调用 Rust 函数并传递字符串参数?》,以下内容将会涉及到,若是在学习中对其中部分知识点有疑问,或许看了本文就能帮到你!

问题内容

我一直在尝试将字符串传递给 rust 函数(编译为 wasm),但是据我了解,现在无法直接传递字符串,因为“str”不是“中的类型” ffi 世界”(至少 rust 编译器是这么说的): = 帮助:考虑使用 `*const u8` 和长度代替

所以我所做的是将函数更改为这种形式(而不是使用简单的 &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::();
    let layout = layout::from_size_align_unchecked(size, align);
    alloc(layout)
}

这是一个使用像这样的 alloc 函数的 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.instance”类型)。
  • 我不知道如何在 go 中执行 unit8buffer 的操作。

关于 wasm 内存的好读:(https://radu-matei.com/blog/practical-guide-to-wasm-memory/#exchang-strings- between-modules-and-runtimes)


解决方案


我花了一些时间才了解 wasmtime go 包的工作原理,但最终我解决了我的问题:

func main() {
    dir, err := ioutil.TempDir("", "out")
    check(err)
    defer os.RemoveAll(dir)
    stdoutPath := filepath.Join(dir, "stdout")

    engine := wasmtime.NewEngine()
    store := wasmtime.NewStore(engine)

    linker := wasmtime.NewLinker(store)

    // Configure WASI imports to write stdout into a file.
    wasiConfig := wasmtime.NewWasiConfig()
    wasiConfig.SetStdoutFile(stdoutPath)


    wasi, err := wasmtime.NewWasiInstance(store, wasiConfig, "wasi_snapshot_preview1")
    check(err)

    // Link WASI
    err = linker.DefineWasi(wasi)
    check(err)

    // Create our module
    module, err := wasmtime.NewModuleFromFile(store.Engine, "wasm_file.wasm")
    check(err)
    instance, err := linker.Instantiate(module)
    check(err)


    fn := instance.GetExport("greet").Func()
    memory := instance.GetExport("memory").Memory()
    alloc := instance.GetExport("my_alloc").Func()

    // // string for alloc
    size2 := int32(len([]byte("Elvis")))

    // //Allocate memomory
    ptr2, err := alloc.Call(size2)
    pointer, _ := ptr2.(int32)

    buf := memory.UnsafeData()
    for i, v := range []byte("Elvis") {
        buf[pointer+int32(i)] = v
    }

    // Use string func
    _, err = fn.Call(pointer, size2 )
    check(err)
    
    // Print WASM stdout
    out, err := ioutil.ReadFile(stdoutPath)
    check(err)
    fmt.Print(string(out))
}

今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>