首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用字符串作为参数调用Rust函数?

如何使用字符串作为参数调用Rust函数?
EN

Stack Overflow用户
提问于 2021-01-18 17:00:07
回答 1查看 796关注 0票数 3

我一直试图将一个字符串传递给一个Rust函数(编译为Wasm),但据我所知,现在没有办法直接传递字符串,因为"str“不是"FFI世界”中的一个类型(至少锈蚀编译器是这么说的):= help: consider using `*const u8` and a length instead

因此,我所做的是将函数更改为这个表单(而不是使用一个简单的&str类型):

代码语言:javascript
复制
#[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模块是沙箱化的,所以它们不能像普通应用程序那样使用普通指针。因此,我必须使用这样的函数将内存分配到模块的线性内存中:

代码语言:javascript
复制
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函数:

代码语言:javascript
复制
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“线上,原因如下:

  • I在Go中找不到相当于"*wasmtime.Instance“的"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)

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-01-20 10:30:48

我花了一点时间才真正理解了这个打包程序是如何工作的,但最终我解决了我的问题:

代码语言:javascript
复制
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))
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65778901

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档