update bridge
This commit is contained in:
		
							parent
							
								
									5a771cc80d
								
							
						
					
					
						commit
						4aefd0446f
					
				
							
								
								
									
										101
									
								
								bridge.go
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								bridge.go
									
									
									
									
									
								
							@ -2,35 +2,51 @@ package wasm
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding/binary"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"github.com/wasmerio/go-ext-wasm/wasmer"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func init() {
 | 
			
		||||
	Bridge = new(bridge)
 | 
			
		||||
var undefined = &struct{}{}
 | 
			
		||||
var bridges = map[string]*Bridge{}
 | 
			
		||||
var mu sync.RWMutex // to protect bridges
 | 
			
		||||
 | 
			
		||||
type context struct {
 | 
			
		||||
	n string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Bridge connects go wasm builds
 | 
			
		||||
var Bridge *bridge
 | 
			
		||||
func setBridge(b *Bridge) unsafe.Pointer {
 | 
			
		||||
	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
 | 
			
		||||
	vmExit   bool
 | 
			
		||||
	exitCode int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GoBridge returns a new bridge.
 | 
			
		||||
func (b *bridge) InitWASM(file string, imports *wasmer.Imports) (err error) {
 | 
			
		||||
	bytes, err := wasmer.ReadBytes(file)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
func (b *Bridge) InitWASMBytes(name string, bytes []byte, imports *wasmer.Imports) error {
 | 
			
		||||
	if imports == nil {
 | 
			
		||||
		imports = wasmer.NewImports()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = b.addImports(imports)
 | 
			
		||||
	b.name = name
 | 
			
		||||
	err := b.addImports(imports)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@ -41,11 +57,21 @@ func (b *bridge) InitWASM(file string, imports *wasmer.Imports) (err error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b.instance = inst
 | 
			
		||||
	inst.SetContextData(setBridge(b))
 | 
			
		||||
	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.
 | 
			
		||||
func (b *bridge) Run() error {
 | 
			
		||||
func (b *Bridge) Run() error {
 | 
			
		||||
	defer b.instance.Close()
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *bridge) mem() []byte {
 | 
			
		||||
func (b *Bridge) mem() []byte {
 | 
			
		||||
	return b.instance.Memory.Data()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b bridge) setInt64(offset int32, v int64) {
 | 
			
		||||
func (b Bridge) setInt64(offset int32, v int64) {
 | 
			
		||||
	mem := b.mem()
 | 
			
		||||
	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()
 | 
			
		||||
	array := binary.LittleEndian.Uint64(mem[addr+0:])
 | 
			
		||||
	length := binary.LittleEndian.Uint64(mem[addr+8:])
 | 
			
		||||
	return mem[array : array+length]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b bridge) loadString(addr int32) string {
 | 
			
		||||
func (b Bridge) loadString(addr int32) string {
 | 
			
		||||
	d := b.loadSlice(addr)
 | 
			
		||||
	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
 | 
			
		||||
func debug(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
	log.Println(a)
 | 
			
		||||
func debug(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	log.Println(sp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export wexit
 | 
			
		||||
func wexit(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
	Bridge.vmExit = true
 | 
			
		||||
	mem := Bridge.mem()
 | 
			
		||||
	Bridge.exitCode = int(binary.LittleEndian.Uint32(mem[a+8:]))
 | 
			
		||||
	fmt.Println("Wasm exited with code", Bridge.exitCode)
 | 
			
		||||
func wexit(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	b := getBridge(ctx)
 | 
			
		||||
	b.vmExit = true
 | 
			
		||||
	mem := b.mem()
 | 
			
		||||
	b.exitCode = int(binary.LittleEndian.Uint32(mem[sp+8:]))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export wwrite
 | 
			
		||||
func wwrite(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
	fmt.Println("wasm write", a)
 | 
			
		||||
func wwrite(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	fmt.Println("wasm write", sp)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export nanotime
 | 
			
		||||
func nanotime(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
func nanotime(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	n := time.Now().UnixNano()
 | 
			
		||||
	Bridge.setInt64(a+8, n)
 | 
			
		||||
	getBridge(ctx).setInt64(sp+8, n)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export walltime
 | 
			
		||||
func walltime(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
func walltime(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	fmt.Println("wall time")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export scheduleCallback
 | 
			
		||||
func scheduleCallback(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
func scheduleCallback(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	fmt.Println("schedule callback")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export clearScheduledCallback
 | 
			
		||||
func clearScheduledCallback(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
func clearScheduledCallback(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	fmt.Println("clear scheduled callback")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export getRandomData
 | 
			
		||||
func getRandomData(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
	s := Bridge.loadSlice(a + 8)
 | 
			
		||||
func getRandomData(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	s := getBridge(ctx).loadSlice(sp + 8)
 | 
			
		||||
	_, err := rand.Read(s)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		fmt.Println("failed: getRandomData", err)
 | 
			
		||||
@ -86,73 +86,78 @@ func getRandomData(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export stringVal
 | 
			
		||||
func stringVal(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
func stringVal(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	fmt.Println("stringVal")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export valueGet
 | 
			
		||||
func valueGet(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
	str := Bridge.loadString(a + 16)
 | 
			
		||||
	fmt.Println("valueGet", str)
 | 
			
		||||
func valueGet(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	b := getBridge(ctx)
 | 
			
		||||
	str := b.loadString(sp + 16)
 | 
			
		||||
	val := b.loadValue(sp + 8)
 | 
			
		||||
	fmt.Println("valueGet", str, val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export valueSet
 | 
			
		||||
func valueSet(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
	fmt.Println("valueSet")
 | 
			
		||||
func valueSet(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	str := getBridge(ctx).loadString(sp + 16)
 | 
			
		||||
	fmt.Println("valueSet", str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export valueIndex
 | 
			
		||||
func valueIndex(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
func valueIndex(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	fmt.Println("valueIndex")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export valueSetIndex
 | 
			
		||||
func valueSetIndex(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
func valueSetIndex(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	fmt.Println("valueSetIndex")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export valueCall
 | 
			
		||||
func valueCall(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
	fmt.Println("valueCall")
 | 
			
		||||
func valueCall(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	str := getBridge(ctx).loadString(sp + 16)
 | 
			
		||||
	fmt.Println("valueCall", str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export valueInvoke
 | 
			
		||||
func valueInvoke(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
func valueInvoke(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	fmt.Println("valueInvoke")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export valueNew
 | 
			
		||||
func valueNew(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
	fmt.Println("valueNew")
 | 
			
		||||
func valueNew(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	str := getBridge(ctx).loadString(sp + 16)
 | 
			
		||||
	fmt.Println("valueNew", str)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export valueLength
 | 
			
		||||
func valueLength(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
func valueLength(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	fmt.Println("valueLength")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export valuePrepareString
 | 
			
		||||
func valuePrepareString(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
func valuePrepareString(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	fmt.Println("valuePrepareString")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export valueLoadString
 | 
			
		||||
func valueLoadString(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
func valueLoadString(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	fmt.Println("valueLoadString")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export scheduleTimeoutEvent
 | 
			
		||||
func scheduleTimeoutEvent(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
func scheduleTimeoutEvent(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	fmt.Println("scheduleTimeoutEvent")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//export clearTimeoutEvent
 | 
			
		||||
func clearTimeoutEvent(ctx unsafe.Pointer, a int32) {
 | 
			
		||||
func clearTimeoutEvent(ctx unsafe.Pointer, sp int32) {
 | 
			
		||||
	fmt.Println("clearTimeoutEvent")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// addImports adds go bridge imports in "go" namespace.
 | 
			
		||||
func (b *bridge) addImports(imps *wasmer.Imports) error {
 | 
			
		||||
// addImports adds go Bridge imports in "go" namespace.
 | 
			
		||||
func (b *Bridge) addImports(imps *wasmer.Imports) error {
 | 
			
		||||
	imps = imps.Namespace("go")
 | 
			
		||||
	var is = []struct {
 | 
			
		||||
		name string
 | 
			
		||||
 | 
			
		||||
@ -7,12 +7,13 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
		log.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := wasmgo.Bridge.Run(); err != nil {
 | 
			
		||||
	if err := b.Run(); err != nil {
 | 
			
		||||
		log.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user