update bridge
parent
5a771cc80d
commit
4aefd0446f
101
bridge.go
101
bridge.go
|
@ -2,35 +2,51 @@ package wasm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
"sync"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/wasmerio/go-ext-wasm/wasmer"
|
"github.com/wasmerio/go-ext-wasm/wasmer"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
var undefined = &struct{}{}
|
||||||
Bridge = new(bridge)
|
var bridges = map[string]*Bridge{}
|
||||||
|
var mu sync.RWMutex // to protect bridges
|
||||||
|
|
||||||
|
type context struct {
|
||||||
|
n string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bridge connects go wasm builds
|
func setBridge(b *Bridge) unsafe.Pointer {
|
||||||
var Bridge *bridge
|
mu.Lock()
|
||||||
|
defer mu.Unlock()
|
||||||
|
bridges[b.name] = b
|
||||||
|
return unsafe.Pointer(&context{n: b.name})
|
||||||
|
}
|
||||||
|
|
||||||
type bridge struct {
|
func getBridge(ctx unsafe.Pointer) *Bridge {
|
||||||
|
ictx := wasmer.IntoInstanceContext(ctx)
|
||||||
|
c := (*context)(ictx.Data())
|
||||||
|
mu.RLock()
|
||||||
|
defer mu.RUnlock()
|
||||||
|
return bridges[c.n]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Bridge struct {
|
||||||
|
name string
|
||||||
instance wasmer.Instance
|
instance wasmer.Instance
|
||||||
vmExit bool
|
vmExit bool
|
||||||
exitCode int
|
exitCode int
|
||||||
}
|
}
|
||||||
|
|
||||||
// GoBridge returns a new bridge.
|
func (b *Bridge) InitWASMBytes(name string, bytes []byte, imports *wasmer.Imports) error {
|
||||||
func (b *bridge) InitWASM(file string, imports *wasmer.Imports) (err error) {
|
|
||||||
bytes, err := wasmer.ReadBytes(file)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if imports == nil {
|
if imports == nil {
|
||||||
imports = wasmer.NewImports()
|
imports = wasmer.NewImports()
|
||||||
}
|
}
|
||||||
|
|
||||||
err = b.addImports(imports)
|
b.name = name
|
||||||
|
err := b.addImports(imports)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -41,11 +57,21 @@ func (b *bridge) InitWASM(file string, imports *wasmer.Imports) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
b.instance = inst
|
b.instance = inst
|
||||||
|
inst.SetContextData(setBridge(b))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Bridge) InitWASM(name, file string, imports *wasmer.Imports) (err error) {
|
||||||
|
bytes, err := wasmer.ReadBytes(file)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.InitWASMBytes(name, bytes, imports)
|
||||||
|
}
|
||||||
|
|
||||||
// Run start the wasm instance.
|
// Run start the wasm instance.
|
||||||
func (b *bridge) Run() error {
|
func (b *Bridge) Run() error {
|
||||||
defer b.instance.Close()
|
defer b.instance.Close()
|
||||||
|
|
||||||
run := b.instance.Exports["run"]
|
run := b.instance.Exports["run"]
|
||||||
|
@ -62,26 +88,65 @@ func (b *bridge) Run() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("WASM exited with code: %v\n", b.exitCode)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *bridge) mem() []byte {
|
func (b *Bridge) mem() []byte {
|
||||||
return b.instance.Memory.Data()
|
return b.instance.Memory.Data()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b bridge) setInt64(offset int32, v int64) {
|
func (b Bridge) setInt64(offset int32, v int64) {
|
||||||
mem := b.mem()
|
mem := b.mem()
|
||||||
binary.LittleEndian.PutUint64(mem[offset:], uint64(v))
|
binary.LittleEndian.PutUint64(mem[offset:], uint64(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b bridge) loadSlice(addr int32) []byte {
|
func (b Bridge) setUint64(offset int32, v uint64) {
|
||||||
|
mem := b.mem()
|
||||||
|
binary.LittleEndian.PutUint64(mem[offset:], v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Bridge) getUnit64(offset int32) uint64 {
|
||||||
|
mem := b.mem()
|
||||||
|
return binary.LittleEndian.Uint64(mem[offset+0:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Bridge) setFloat64(offset int32, v float64) {
|
||||||
|
uf := math.Float64bits(v)
|
||||||
|
b.setUint64(offset, uf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Bridge) getFloat64(offset int32) float64 {
|
||||||
|
uf := b.getUnit64(offset)
|
||||||
|
return math.Float64frombits(uf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Bridge) getUint32(offset int32) uint32 {
|
||||||
|
return binary.LittleEndian.Uint32(b.mem()[offset+0:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Bridge) loadSlice(addr int32) []byte {
|
||||||
mem := b.mem()
|
mem := b.mem()
|
||||||
array := binary.LittleEndian.Uint64(mem[addr+0:])
|
array := binary.LittleEndian.Uint64(mem[addr+0:])
|
||||||
length := binary.LittleEndian.Uint64(mem[addr+8:])
|
length := binary.LittleEndian.Uint64(mem[addr+8:])
|
||||||
return mem[array : array+length]
|
return mem[array : array+length]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b bridge) loadString(addr int32) string {
|
func (b Bridge) loadString(addr int32) string {
|
||||||
d := b.loadSlice(addr)
|
d := b.loadSlice(addr)
|
||||||
return string(d)
|
return string(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b Bridge) loadValue(addr int32) interface{} {
|
||||||
|
f := b.getFloat64(addr)
|
||||||
|
if f == 0 {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
if !math.IsNaN(f) {
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
// return value instead of uint32
|
||||||
|
return b.getUint32(addr)
|
||||||
|
}
|
||||||
|
|
77
imports.go
77
imports.go
|
@ -38,47 +38,47 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
//export debug
|
//export debug
|
||||||
func debug(ctx unsafe.Pointer, a int32) {
|
func debug(ctx unsafe.Pointer, sp int32) {
|
||||||
log.Println(a)
|
log.Println(sp)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export wexit
|
//export wexit
|
||||||
func wexit(ctx unsafe.Pointer, a int32) {
|
func wexit(ctx unsafe.Pointer, sp int32) {
|
||||||
Bridge.vmExit = true
|
b := getBridge(ctx)
|
||||||
mem := Bridge.mem()
|
b.vmExit = true
|
||||||
Bridge.exitCode = int(binary.LittleEndian.Uint32(mem[a+8:]))
|
mem := b.mem()
|
||||||
fmt.Println("Wasm exited with code", Bridge.exitCode)
|
b.exitCode = int(binary.LittleEndian.Uint32(mem[sp+8:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
//export wwrite
|
//export wwrite
|
||||||
func wwrite(ctx unsafe.Pointer, a int32) {
|
func wwrite(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("wasm write", a)
|
fmt.Println("wasm write", sp)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export nanotime
|
//export nanotime
|
||||||
func nanotime(ctx unsafe.Pointer, a int32) {
|
func nanotime(ctx unsafe.Pointer, sp int32) {
|
||||||
n := time.Now().UnixNano()
|
n := time.Now().UnixNano()
|
||||||
Bridge.setInt64(a+8, n)
|
getBridge(ctx).setInt64(sp+8, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export walltime
|
//export walltime
|
||||||
func walltime(ctx unsafe.Pointer, a int32) {
|
func walltime(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("wall time")
|
fmt.Println("wall time")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export scheduleCallback
|
//export scheduleCallback
|
||||||
func scheduleCallback(ctx unsafe.Pointer, a int32) {
|
func scheduleCallback(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("schedule callback")
|
fmt.Println("schedule callback")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export clearScheduledCallback
|
//export clearScheduledCallback
|
||||||
func clearScheduledCallback(ctx unsafe.Pointer, a int32) {
|
func clearScheduledCallback(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("clear scheduled callback")
|
fmt.Println("clear scheduled callback")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export getRandomData
|
//export getRandomData
|
||||||
func getRandomData(ctx unsafe.Pointer, a int32) {
|
func getRandomData(ctx unsafe.Pointer, sp int32) {
|
||||||
s := Bridge.loadSlice(a + 8)
|
s := getBridge(ctx).loadSlice(sp + 8)
|
||||||
_, err := rand.Read(s)
|
_, err := rand.Read(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("failed: getRandomData", err)
|
fmt.Println("failed: getRandomData", err)
|
||||||
|
@ -86,73 +86,78 @@ func getRandomData(ctx unsafe.Pointer, a int32) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//export stringVal
|
//export stringVal
|
||||||
func stringVal(ctx unsafe.Pointer, a int32) {
|
func stringVal(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("stringVal")
|
fmt.Println("stringVal")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueGet
|
//export valueGet
|
||||||
func valueGet(ctx unsafe.Pointer, a int32) {
|
func valueGet(ctx unsafe.Pointer, sp int32) {
|
||||||
str := Bridge.loadString(a + 16)
|
b := getBridge(ctx)
|
||||||
fmt.Println("valueGet", str)
|
str := b.loadString(sp + 16)
|
||||||
|
val := b.loadValue(sp + 8)
|
||||||
|
fmt.Println("valueGet", str, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueSet
|
//export valueSet
|
||||||
func valueSet(ctx unsafe.Pointer, a int32) {
|
func valueSet(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("valueSet")
|
str := getBridge(ctx).loadString(sp + 16)
|
||||||
|
fmt.Println("valueSet", str)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueIndex
|
//export valueIndex
|
||||||
func valueIndex(ctx unsafe.Pointer, a int32) {
|
func valueIndex(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("valueIndex")
|
fmt.Println("valueIndex")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueSetIndex
|
//export valueSetIndex
|
||||||
func valueSetIndex(ctx unsafe.Pointer, a int32) {
|
func valueSetIndex(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("valueSetIndex")
|
fmt.Println("valueSetIndex")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueCall
|
//export valueCall
|
||||||
func valueCall(ctx unsafe.Pointer, a int32) {
|
func valueCall(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("valueCall")
|
str := getBridge(ctx).loadString(sp + 16)
|
||||||
|
fmt.Println("valueCall", str)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueInvoke
|
//export valueInvoke
|
||||||
func valueInvoke(ctx unsafe.Pointer, a int32) {
|
func valueInvoke(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("valueInvoke")
|
fmt.Println("valueInvoke")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueNew
|
//export valueNew
|
||||||
func valueNew(ctx unsafe.Pointer, a int32) {
|
func valueNew(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("valueNew")
|
str := getBridge(ctx).loadString(sp + 16)
|
||||||
|
fmt.Println("valueNew", str)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueLength
|
//export valueLength
|
||||||
func valueLength(ctx unsafe.Pointer, a int32) {
|
func valueLength(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("valueLength")
|
fmt.Println("valueLength")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valuePrepareString
|
//export valuePrepareString
|
||||||
func valuePrepareString(ctx unsafe.Pointer, a int32) {
|
func valuePrepareString(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("valuePrepareString")
|
fmt.Println("valuePrepareString")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export valueLoadString
|
//export valueLoadString
|
||||||
func valueLoadString(ctx unsafe.Pointer, a int32) {
|
func valueLoadString(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("valueLoadString")
|
fmt.Println("valueLoadString")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export scheduleTimeoutEvent
|
//export scheduleTimeoutEvent
|
||||||
func scheduleTimeoutEvent(ctx unsafe.Pointer, a int32) {
|
func scheduleTimeoutEvent(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("scheduleTimeoutEvent")
|
fmt.Println("scheduleTimeoutEvent")
|
||||||
}
|
}
|
||||||
|
|
||||||
//export clearTimeoutEvent
|
//export clearTimeoutEvent
|
||||||
func clearTimeoutEvent(ctx unsafe.Pointer, a int32) {
|
func clearTimeoutEvent(ctx unsafe.Pointer, sp int32) {
|
||||||
fmt.Println("clearTimeoutEvent")
|
fmt.Println("clearTimeoutEvent")
|
||||||
}
|
}
|
||||||
|
|
||||||
// addImports adds go bridge imports in "go" namespace.
|
// addImports adds go Bridge imports in "go" namespace.
|
||||||
func (b *bridge) addImports(imps *wasmer.Imports) error {
|
func (b *Bridge) addImports(imps *wasmer.Imports) error {
|
||||||
imps = imps.Namespace("go")
|
imps = imps.Namespace("go")
|
||||||
var is = []struct {
|
var is = []struct {
|
||||||
name string
|
name string
|
||||||
|
|
|
@ -7,12 +7,13 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
err := wasmgo.Bridge.InitWASM("./simple/prog/main.wasm", nil)
|
b := wasmgo.Bridge{}
|
||||||
|
err := b.InitWASM("test", "./simple/prog/main.wasm", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := wasmgo.Bridge.Run(); err != nil {
|
if err := b.Run(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue