hybridgroup / mechanoid

Mechanoid is a framework for WebAssembly applications on embedded systems and IoT devices.
https://mechanoid.io
Apache License 2.0
170 stars 8 forks source link

Draft: Wazergo #11

Closed orsinium closed 4 months ago

orsinium commented 4 months ago

Replaces DefineFunc and funcs with wazergo. Since wazergo works only with wazero, we can't merge it until wazero works better than wasman.

deadprogram commented 4 months ago

Looks like some dependencies missing for the CI to run:

Error: interp/wazero/module.go:6:2: no required module provides package github.com/stealthrocket/wazergo; to add it:
go get github.com/stealthrocket/wazergo
Error: Process completed with exit code 1.
orsinium commented 4 months ago

Yes, I didn't include go.mod yet. If you already want to try it out, go mod tidy should do the trick.

orsinium commented 4 months ago

Also if you're playing with it, here's updated badge.go for wasmbadge:

package badge

import (
    "context"
    "unsafe"

    "github.com/hybridgroup/mechanoid-examples/wasmbadge/devices/display"
    "github.com/hybridgroup/mechanoid/engine"
    "github.com/hybridgroup/mechanoid/interp/wazero"
    "github.com/stealthrocket/wazergo"
    "github.com/stealthrocket/wazergo/types"
    "tinygo.org/x/drivers/pixel"
)

type Badge[T pixel.Color] struct {
    Engine  *engine.Engine
    Display *display.Device[T]
}

func NewDevice[T pixel.Color](e *engine.Engine) *Badge[T] {
    return &Badge[T]{
        Engine: e,
    }
}

func (b *Badge[T]) Init() error {
    if b.Engine == nil {
        return engine.ErrInvalidEngine
    }
    interp := b.Engine.Interpreter.(*wazero.Interpreter)
    err := wazero.AddModule[*Badge[T]](interp, "badge", b, wazergo.Functions[*Badge[T]]{
        "new_big_text": wazergo.F1((*Badge[T]).newBigText),
    })
    if err != nil {
        println(err.Error())
        return err
    }
    err = wazero.AddModule[*Badge[T]](interp, "bigtext", b, wazergo.Functions[*Badge[T]]{
        "set_text1": wazergo.F2((*Badge[T]).bigTextSetText1),
        "set_text2": wazergo.F2((*Badge[T]).bigTextSetText2),
        "show":      wazergo.F1((*Badge[T]).bigTextShow),
    })
    if err != nil {
        println(err.Error())
        return err
    }
    return nil
}

func (b *Badge[T]) UseDisplay(d *display.Device[T]) error {
    b.Display = d
    return nil
}

func (b *Badge[T]) newBigText(_ context.Context, msg types.String) types.Uint32 {
    // create the badge UI element
    bt := NewBigText[T](b.Display, "WASM Badge", string(msg), "")
    if bt == nil {
        return 0
    }
    bt.Show(b.Display)

    id := uint32(b.Engine.Interpreter.References().Add(unsafe.Pointer(bt)))
    return types.Uint32(id)
}

func (b *Badge[T]) bigTextSetText1(_ context.Context, ref types.Uint32, msg types.String) types.Uint32 {
    // get the badge UI element by reference
    p := b.Engine.Interpreter.References().Get(int32(ref))
    if p == uintptr(0) {
        println("bigTextSetText1: reference not found")
        return 0
    }
    bt := (*BigText[T])(unsafe.Pointer(p))
    if bt == nil {
        return 0
    }
    bt.SetText1(string(msg))
    return types.Uint32(len(msg))
}

func (b *Badge[T]) bigTextSetText2(_ context.Context, ref types.Uint32, msg types.String) types.Uint32 {
    // get the badge UI element by reference
    p := b.Engine.Interpreter.References().Get(int32(ref))
    if p == uintptr(0) {
        println("bigTextSetText2: reference not found")
        return 0
    }
    bt := (*BigText[T])(unsafe.Pointer(p))
    if bt == nil {
        return 0
    }
    bt.SetText2(string(msg))
    return types.Uint32(len(msg))
}

func (b *Badge[T]) bigTextShow(_ context.Context, ref types.Uint32) types.Uint32 {
    // get the badge UI element by reference
    p := b.Engine.Interpreter.References().Get(int32(ref))
    if p == uintptr(0) {
        println("bigTextSetText1: reference not found")
        return 0
    }
    bt := (*BigText[T])(unsafe.Pointer(p))
    if bt == nil {
        return 0
    }
    bt.Show(b.Display)

    return 1
}

func (b *Badge[T]) Close(context.Context) error {
    return nil
}
deadprogram commented 4 months ago

cc @evacchi :smile_cat:

deadprogram commented 4 months ago

This is running on PyBadge using wazero runtime. It is starting to work, but a lot more effort still needed here.

image

deadprogram commented 4 months ago

Closing since we have merged #17