veandco / go-sdl2

SDL2 binding for Go
https://godoc.org/github.com/veandco/go-sdl2
BSD 3-Clause "New" or "Revised" License
2.17k stars 219 forks source link

Linux->Windows10 cross compiled executable hangs/not responding (for loop drawing) #453

Closed godstanis closed 4 years ago

godstanis commented 4 years ago

From: Ubuntu 18.04.4 To: Windows 10 x64 [17763.1039] Runtime win sdl2 dll: SDL2-2.0.10-win32-x64.zip (http://libsdl.org/download-2.0.php)

I compile it to windows with the command in your documentation.


Hello guys, I appreciate your work, library is great!) I guess I'm doing something wrong, but it works on Linux perfectly... I don't do any async stuff so tricks from FAQ didn't help.

I'm trying to cross-compile a project written with this library to Windows but the final .exe is not working correctly. By default, it just hangs after any attempts to close/click on it. If I set the executable's compatibility mode to Windows 7 it runs ok, but the window is not resizable or movable at all, and it hangs eventually but I could not figure out the conditions for win7 compatibility crashes.

Minimal code to reproduce this:

package main

import "github.com/veandco/go-sdl2/sdl"

func main() {
    _ = sdl.Init(sdl.INIT_VIDEO)
    window, _ := sdl.CreateWindow("Sdl2", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, 500, 500, sdl.WINDOW_RESIZABLE)

    for {
        s, _ := window.GetSurface()
        s.FillRect(&sdl.Rect{X: 30, Y: 20, W: 100, H: 50}, 0x00FF00)
        window.UpdateSurface()
        sdl.Delay(16)
    }
}
veeableful commented 4 years ago

Hi @godstanis, have you tried listening to sdl.QuitEvent? Something like this?

package main

import "github.com/veandco/go-sdl2/sdl"

func main() {
    _ = sdl.Init(sdl.INIT_VIDEO)
    window, _ := sdl.CreateWindow("Sdl2", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, 500, 500, sdl.WINDOW_RESIZABLE)
    running := true

    for running {
        for event := sdl.PollEvent(); event != nil; event = sdl.PollEvent() {
            switch event.(type) {
            case *sdl.QuitEvent:
                running = false
            }
        }

        s, _ := window.GetSurface()
        s.FillRect(&sdl.Rect{X: 30, Y: 20, W: 100, H: 50}, 0x00FF00)
        window.UpdateSurface()
        sdl.Delay(16)
    }
}
godstanis commented 4 years ago

Hmm, thanks @veeableful, it works when i listen to events in the main thread :joy_cat: . I have actually been using WaitEvent method for a while in a separate goroutine (it feels a bit more comfortable and natural to do this thing separately), something like this:

func main() {
    _ = sdl.Init(sdl.INIT_VIDEO)
    window, _ := sdl.CreateWindow("Sdl2", sdl.WINDOWPOS_UNDEFINED, sdl.WINDOWPOS_UNDEFINED, 500, 500, sdl.WINDOW_RESIZABLE)

    go func() {
        for {
            event := sdl.WaitEvent()
            switch event.(type) {
            case *sdl.QuitEvent:
                os.Exit(0)
            }
        }
    }()

    for {
        s, _ := window.GetSurface()
        s.FillRect(&sdl.Rect{X: 30, Y: 20, W: 100, H: 50}, 0x00FF00)
        window.UpdateSurface()
        sdl.Delay(16)
    }
}

I heard that there are some problems with multithreading and sdl2, but it actually works perfectly on my Ubuntu. Is there a reason why it fails on win? Differences in lib implementations?

Just asking, the actual issue is solved, thanks :+1:

veeableful commented 4 years ago

I must admit I don't know exactly why either :sweat_smile:.. but I have had applications freeze when using tight loop without some sort of delay / sleep on Windows GUI applications though I also do that just in general so as to free the CPU up to handle other things. Perhaps the event code can be rewritten to receive in batches? e.g. get all the available events with a for-loop and sleep for a while. According to the SDL2 wiki, the event code should also be on the main thread.