[英]How to use Go slice when calling WebAssembly code in Go?
I want to calculate the sum of an array using WebAssembly in Go:我想在 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)
}
}
But this code is not giving me the expected result.但是这段代码没有给我预期的结果。 Logic for my code is to calculate the sum of an array.我的代码的逻辑是计算数组的总和。 Values to the array is giving during runtime.数组的值在运行时给出。
What changes I need to do?我需要做哪些改变?
My rust code looks like this我的锈代码看起来像这样
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
}
Thanks谢谢
Copy data to WebAssembly memory (for example WebAssembly memory address 0):将数据复制到 WebAssembly 内存(例如 WebAssembly 内存地址 0):
a := []int32{10, 20, 30, 40}
// Copy data to wasm memory:
bytes := instance.Memory.Data()
for i, v := range a {
binary.LittleEndian.PutUint32(bytes[4*i:], uint32(v))
}
Get the bar
exported function from the WebAssembly instance:从 WebAssembly 实例获取bar
导出函数:
bar := instance.Exports["bar"]
Call that exported function with WebAssembly memory address and length:使用 WebAssembly 内存地址和长度调用导出的函数:
result, err := bar(0, 4)
if err != nil {
panic(err)
}
fmt.Println(result)
The main.go
file: main.go
文件:
package main
import (
"encoding/binary"
"fmt"
wasm "github.com/wasmerio/go-ext-wasm/wasmer"
)
func main() {
// Instantiate the module.
wasmbyte, err := wasm.ReadBytes("test.wasm")
if err != nil {
panic(err)
}
instance, err := wasm.NewInstance(wasmbyte)
if err != nil {
panic(err)
}
defer instance.Close()
hasmemory := instance.HasMemory()
fmt.Println("it has memory:", hasmemory)
a := []int32{10, 20, 30, 40}
// Copy data to wasm memory:
bytes := instance.Memory.Data()
for i, v := range a {
binary.LittleEndian.PutUint32(bytes[4*i:], uint32(v))
}
bar := instance.Exports["bar"]
result, err := bar(0, 4)
if err != nil {
panic(err)
}
fmt.Println(result)
}
Output ( go run main.go
):输出( go run main.go
):
it has memory: true
100
And the following src/lib.rs
file has the same wasm binary (since Rust slice has only pointer and length):并且以下src/lib.rs
文件具有相同的 wasm 二进制文件(因为 Rust 切片只有指针和长度):
#[no_mangle]
pub extern "C" fn bar(slice: &[i32]) -> i32 {
slice.iter().sum()
}
Convert to test.wasm
:转换为test.wasm
:
rustc --target wasm32-unknown-unknown -O --crate-type=cdylib src/lib.rs -o test.wasm
Output converted to test.wat
( wasm2wat test.wasm -o test.wat
) to see the function $bar
arguments ( param i32 i32
):输出转换为test.wat
( wasm2wat test.wasm -o test.wat
) 以查看函数$bar
参数 ( param i32 i32
):
(module
(type (;0;) (func (param i32 i32) (result i32)))
(func $bar (type 0) (param i32 i32) (result i32)
(local i32)
block ;; label = @1
local.get 1
br_if 0 (;@1;)
i32.const 0
return
end
local.get 1
i32.const 2
i32.shl
local.set 2
i32.const 0
local.set 1
loop ;; label = @1
local.get 0
i32.load
local.get 1
i32.add
local.set 1
local.get 0
i32.const 4
i32.add
local.set 0
local.get 2
i32.const -4
i32.add
local.tee 2
br_if 0 (;@1;)
end
local.get 1)
(table (;0;) 1 1 funcref)
(memory (;0;) 16)
(global (;0;) (mut i32) (i32.const 1048576))
(global (;1;) i32 (i32.const 1048576))
(global (;2;) i32 (i32.const 1048576))
(export "memory" (memory 0))
(export "bar" (func $bar))
(export "__data_end" (global 1))
(export "__heap_base" (global 2)))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.