Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mismatched types gioui.org/ui.pc and . when importing Gio package #320

Closed
theclapp opened this issue Jul 31, 2019 · 11 comments
Closed

mismatched types gioui.org/ui.pc and . when importing Gio package #320

theclapp opened this issue Jul 31, 2019 · 11 comments
Labels
area/core bug Something isn't working

Comments

@theclapp
Copy link

Possibly related to #90 or #308.

I am trying to run the Gio "hello, world" program from within Yaegi. (Toplevel here.) Yaegi throws an error on this line:

func (r *OpsReader) Decode() (EncodedOp, bool) {
	if r.ops == nil {
		return EncodedOp{}, false
	}
	for {
		if len(r.stack) > 0 {
			b := r.stack[len(r.stack)-1]
			if r.pc == b.endPC {
			// ^^^ error here
			// /path/to/gioui.org/ui/ops.go:265:7: mismatched types gioui.org/ui.pc and .

As indicated, the error is mismatched types gioui.org/ui.pc and . .

So first of all, the error message appears to be truncated. And second of all, r.pc and b.endPC are the same type.

If I try to import the package multiple times, it fails twice, then succeeds, and then panics:

% rlwrap yaegi
> import    "gioui.org/ui"
/Users/lmc/src/gioui.org/ui/ops.go:265:7: mismatched types gioui.org/ui.pc and .
> import    "gioui.org/ui"
/Users/lmc/src/gioui.org/ui/ops.go:265:7: mismatched types gioui.org/ui.pc and .
> import    "gioui.org/ui"
0xc0000a14e0
> import    "gioui.org/ui"
/Users/lmc/src/gioui.org/ui/internal/ops/ops.go:6:7: panic
panic: reflect.Set: value of type int is not assignable to type uint8 [recovered]
	panic: reflect.Set: value of type int is not assignable to type uint8
@ldez ldez added area/core bug Something isn't working labels Jul 31, 2019
@mvertes
Copy link
Member

mvertes commented Aug 7, 2019

Thanks for the report. Importing the same package multiple times is not well handled and may cause undefined behaviour, in addition to the initial import mismatch type ... which should not occur in the first place.

@mpl
Copy link
Collaborator

mpl commented Aug 27, 2020

@theclapp I'm trying to reproduce, but gioui.org/ui does not seem to exist anymore, and the links you provided are 404s now. Could you please provide a valid (and complete this time) sample for reproduction?

@theclapp
Copy link
Author

Sorry about that, and thanks for checking in on this bug.

A permalink to the current Gio hello.go example is here. The full-text is

// SPDX-License-Identifier: Unlicense OR MIT

package main

// A simple Gio program. See https://gioui.org for more information.

import (
	"image/color"
	"log"
	"os"

	"gioui.org/app"
	"gioui.org/io/system"
	"gioui.org/layout"
	"gioui.org/op"
	"gioui.org/text"
	"gioui.org/widget/material"

	"gioui.org/font/gofont"
)

func main() {
	go func() {
		w := app.NewWindow()
		if err := loop(w); err != nil {
			log.Fatal(err)
		}
		os.Exit(0)
	}()
	app.Main()
}

func loop(w *app.Window) error {
	th := material.NewTheme(gofont.Collection())
	var ops op.Ops
	for {
		e := <-w.Events()
		switch e := e.(type) {
		case system.DestroyEvent:
			return e.Err
		case system.FrameEvent:
			gtx := layout.NewContext(&ops, e)
			l := material.H1(th, "Hello, Gio")
			maroon := color.RGBA{127, 0, 0, 255}
			l.Color = maroon
			l.Alignment = text.Middle
			l.Layout(gtx)
			e.Frame(gtx.Ops)
		}
	}
}

But it might be moot at this point. Does yaegi support unsafe? Trying the above hello.go with current yaegi gets this:

yaegi hello.go
unable to find source related to: "unsafe"

So if y'all don't support unsafe then I don't think the rest of it matters.

The specific line I cited in func (r *OpsReader) Decode is now here, in case that helps. Whether it'd still be a problem, I can't tell.

Again though, since Gio uses unsafe, if you don't support unsafe, then please feel free to close this issue.

@mpl
Copy link
Collaborator

mpl commented Aug 31, 2020

Yes, by default unsafe is disabled in yaegi.

@mpl
Copy link
Collaborator

mpl commented Nov 2, 2020

@theclapp btw, support for unsafe has been introduced now, notably through the use of the -unsafe option for yaegi run.
Is this issue still relevant?

@theclapp
Copy link
Author

Is this issue still relevant?

Not as such, in that it's not crashing on that problem any more.

Yaegi still cannot run the Gio "hello" program directly:

% yaegi run -unsafe hello.go
run: hello.go:12:2: [...long import chain ...]/src/gioui.org/internal/glimpl/gl_unix.go:200:8: import "C" error: unable to find source related to: "C"

@theclapp
Copy link
Author

I did figure out how to get Yaegi to call already-compiled Gio code, and I think that's good enough.

// SPDX-License-Identifier: Unlicense OR MIT

package main

// A simple Gio program. See https://gioui.org for more information.

import (
	"fmt"
	"image/color"
	"os"
	"reflect"
	"time"

	"github.com/traefik/yaegi/interp"
	"github.com/traefik/yaegi/stdlib"
	"github.com/traefik/yaegi/stdlib/unrestricted"

	"gioui.org/app"
	"gioui.org/font/gofont"
	"gioui.org/io/system"
	"gioui.org/layout"
	"gioui.org/op"
	"gioui.org/text"
	"gioui.org/widget/material"
)

func main() {
	i := interp.New(interp.Options{})
	i.Use(stdlib.Symbols)
	i.Use(unrestricted.Symbols)

	i.Use(map[string]map[string]reflect.Value{
		"gioui.org/app": {
			"NewWindow": reflect.ValueOf(app.NewWindow),
			"Main":      reflect.ValueOf(app.Main),
		},
		"ext": {
			"loop": reflect.ValueOf(loop),
		},
	})

	fmt.Println("Starting yaegi code")
	_, err := i.Eval(`
	   package main

	   import (
			"fmt"
			"log"
			"os"

			"ext" // see i.Use() above
			"gioui.org/app"
		)

		var invalidate func()

		var s = "Hello, Gio!"

		func Start() {
			fmt.Println("In yaegi code")
			go func() {
				fmt.Println("main func starting")
				w := app.NewWindow()
				invalidate = func() { w.Invalidate() }
				if err := ext.loop(w, func() string { return s }); err != nil {
					log.Fatal(err)
				}
				os.Exit(0)
			}()
			app.Main()
		}
	`)
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		os.Exit(1)
	}

	// Reassign an interpreted variable while the GUI is running.
	go func() {
		time.Sleep(2 * time.Second)
		fmt.Println("redefining s")
		_, err := i.Eval(`
			s = "hey look this changed"
			invalidate()
		`)
		if err != nil {
			fmt.Printf("Error: %v\n", err)
		}
		fmt.Println("done redefining s")
	}()

	_, err = i.Eval("Start()")
	if err != nil {
		fmt.Printf("Error: %v\n", err)
	}
	fmt.Println("Yaegi code returned")
}

func loop(w *app.Window, f func() string) error {
	fmt.Println("loop func starting")
	th := material.NewTheme(gofont.Collection())
	var ops op.Ops
	for {
		e := <-w.Events()
		switch e := e.(type) {
		case system.DestroyEvent:
			return e.Err
		case system.FrameEvent:
			gtx := layout.NewContext(&ops, e)
			// l := material.H1(th, "Hello, Gio")
			l := material.H1(th, f())
			maroon := color.NRGBA{R: 127, G: 0, B: 0, A: 255}
			l.Color = maroon
			l.Alignment = text.Middle
			l.Layout(gtx)
			e.Frame(gtx.Ops)
		}
	}
}

@theclapp
Copy link
Author

@whereswaldon beat me to it, by a long shot (in terms of functionality; he posted this yesterday):

demo.mp4

Code here.

@mvertes
Copy link
Member

mvertes commented Jan 30, 2021

Very nice integration of yaegi with a pre-compiled package, here gio (where there is no other choice, due to the C binding). Congrats! A playground for graphic UI makes also a lot of sense 👍

@mpl
Copy link
Collaborator

mpl commented Feb 1, 2021

@whereswaldon beat me to it, by a long shot (in terms of functionality; he posted this yesterday):

demo.mp4
Code here.

What a cool demo!

@whereswaldon
Copy link
Contributor

Thanks! I plan to extend that demo to be a playground for gio a la play.golang.org. Yaegi works just fine when compiled to WASM, which enables some really cool applications! Thanks to everyone who built it!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/core bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants