在 Go 中调用 WebAssembly 代码时如何使用 Go slice?

我想在 Go 中使用 WebAssembly 计算数组的总和:


package main


import (

    "encoding/binary"

    "encoding/hex"

    "fmt"


    wasm "github.com/wasmerio/go-ext-wasm/wasmer"

)


const length int32 = 4


func main() {

    // Instantiate the module.

    wasmbyte, _ := wasm.ReadBytes("test.wasm")

    instance, _ := wasm.NewInstance(wasmbyte)

    defer instance.Close()

    hasmemory := instance.HasMemory()

    fmt.Println("it has memory:", (hasmemory))


    a := []int32{1, 2, 3, 4}

    var i int32

    var ptr [length]*int32


    for i = 0; i < length; i++ {

        ptr[i] = &a[i]

        fmt.Printf("Value of a[%d] = %d\n", i, *ptr[i])


        // pass int value

        // lengths := binary.LittleEndian.Uint32(a)

        // fmt.Printf("customLen=%d\n", int32(lengths))

        // result := int32(lengths)


        allocateResult, err := instance.Exports["bar"](*ptr[i], length)

        if err != nil {

            fmt.Println("error is here", err)

        }


        binary.LittleEndian.PutUint32(instance.Memory.Data()[0:4], uint32(length))


        inputPointer := allocateResult.ToI32()


        //  Write the subject into the memory.

        memory := instance.Memory.Data()[inputPointer:]

        binary.LittleEndian.Uint32(memory)


        resp := hex.EncodeToString(memory)

        fmt.Println("resp:", resp)


    }

}

但是这段代码并没有给我预期的结果。我的代码的逻辑是计算数组的总和。数组的值在运行时给出。

我需要做什么改变?


我的 rust 代码看起来像这样


use std::os::raw::c_int;


#[no_mangle]

pub extern fn bar(my_array: *const c_int, length: c_int) -> *mut c_int{

    let slice = unsafe { std::slice::from_raw_parts(my_array, length as usize) };

    let resp: i32 = slice.iter().sum();


    resp as *mut c_int

}

谢谢


天涯尽头无女友
浏览 116回答 1
1回答

蛊毒传说

将数据复制到 WebAssembly 内存(例如 WebAssembly 内存地址 0):&nbsp; &nbsp; a := []int32{10, 20, 30, 40}&nbsp; &nbsp; // Copy data to wasm memory:&nbsp; &nbsp; bytes := instance.Memory.Data()&nbsp; &nbsp; for i, v := range a {&nbsp; &nbsp; &nbsp; &nbsp; binary.LittleEndian.PutUint32(bytes[4*i:], uint32(v))&nbsp; &nbsp; }从 WebAssembly 实例中获取bar导出的函数:&nbsp; &nbsp; bar := instance.Exports["bar"]使用 WebAssembly 内存地址和长度调用导出的函数:&nbsp; &nbsp; result, err := bar(0, 4)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println(result)main.go文件 :package mainimport (&nbsp; &nbsp; "encoding/binary"&nbsp; &nbsp; "fmt"&nbsp; &nbsp; wasm "github.com/wasmerio/go-ext-wasm/wasmer")func main() {&nbsp; &nbsp; // Instantiate the module.&nbsp; &nbsp; wasmbyte, err := wasm.ReadBytes("test.wasm")&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; }&nbsp; &nbsp; instance, err := wasm.NewInstance(wasmbyte)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; }&nbsp; &nbsp; defer instance.Close()&nbsp; &nbsp; hasmemory := instance.HasMemory()&nbsp; &nbsp; fmt.Println("it has memory:", hasmemory)&nbsp; &nbsp; a := []int32{10, 20, 30, 40}&nbsp; &nbsp; // Copy data to wasm memory:&nbsp; &nbsp; bytes := instance.Memory.Data()&nbsp; &nbsp; for i, v := range a {&nbsp; &nbsp; &nbsp; &nbsp; binary.LittleEndian.PutUint32(bytes[4*i:], uint32(v))&nbsp; &nbsp; }&nbsp; &nbsp; bar := instance.Exports["bar"]&nbsp; &nbsp; result, err := bar(0, 4)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Println(result)}输出(go run main.go):it has memory: true100以下src/lib.rs文件具有相同的 wasm 二进制文件(因为 Rust 切片只有指针和长度):#[no_mangle]pub extern "C" fn bar(slice: &[i32]) -> i32 {&nbsp; &nbsp; slice.iter().sum()}转换为test.wasm:rustc --target wasm32-unknown-unknown -O --crate-type=cdylib src/lib.rs&nbsp; -o test.wasm输出转换为test.wat( wasm2wat test.wasm -o test.wat) 以查看函数$bar参数 ( param i32 i32):(module&nbsp; (type (;0;) (func (param i32 i32) (result i32)))&nbsp; (func $bar (type 0) (param i32 i32) (result i32)&nbsp; &nbsp; (local i32)&nbsp; &nbsp; block&nbsp; ;; label = @1&nbsp; &nbsp; &nbsp; local.get 1&nbsp; &nbsp; &nbsp; br_if 0 (;@1;)&nbsp; &nbsp; &nbsp; i32.const 0&nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; end&nbsp; &nbsp; local.get 1&nbsp; &nbsp; i32.const 2&nbsp; &nbsp; i32.shl&nbsp; &nbsp; local.set 2&nbsp; &nbsp; i32.const 0&nbsp; &nbsp; local.set 1&nbsp; &nbsp; loop&nbsp; ;; label = @1&nbsp; &nbsp; &nbsp; local.get 0&nbsp; &nbsp; &nbsp; i32.load&nbsp; &nbsp; &nbsp; local.get 1&nbsp; &nbsp; &nbsp; i32.add&nbsp; &nbsp; &nbsp; local.set 1&nbsp; &nbsp; &nbsp; local.get 0&nbsp; &nbsp; &nbsp; i32.const 4&nbsp; &nbsp; &nbsp; i32.add&nbsp; &nbsp; &nbsp; local.set 0&nbsp; &nbsp; &nbsp; local.get 2&nbsp; &nbsp; &nbsp; i32.const -4&nbsp; &nbsp; &nbsp; i32.add&nbsp; &nbsp; &nbsp; local.tee 2&nbsp; &nbsp; &nbsp; br_if 0 (;@1;)&nbsp; &nbsp; end&nbsp; &nbsp; local.get 1)&nbsp; (table (;0;) 1 1 funcref)&nbsp; (memory (;0;) 16)&nbsp; (global (;0;) (mut i32) (i32.const 1048576))&nbsp; (global (;1;) i32 (i32.const 1048576))&nbsp; (global (;2;) i32 (i32.const 1048576))&nbsp; (export "memory" (memory 0))&nbsp; (export "bar" (func $bar))&nbsp; (export "__data_end" (global 1))&nbsp; (export "__heap_base" (global 2)))
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go