dsdapobp26141 2019-05-08 17:54
浏览 111
已采纳

在Go中的Goroutine中运行并使用SDL

I have a program with multiple multiple loops, each one ran in a Goroutine. I need to plug or unplug monitors while my program runs, so I have to restart the sdl to let it find my new monitors, I do it by sdl.quit() to quit the last sdl and sdl.init(sdl.InitEverything) to initialize it again. My problem is that I have to handle the sdl events in a loop, If I don't it will become unresponsive, but this loop will block my Main code. I don't need to handle any events like mouse clicks, I just want to show some simple picture and manipulate them, is there any way to stop events or run the whole sdl in a goroutine? I tried but get weird results. This is my struct:

type SDLstruct{
    window *sdl.Window
    renderer *sdl.Renderer
    texture *sdl.Texture
    src, dst sdl.Rect
    event sdl.Event
    Close bool
    winWidth, winHeight int32
}

This function starts a window and a renderer:

func (sdlVars *SDLstruct)StartWindow() (err error) {

    sdlVars.winWidth, sdlVars.winHeight = 1920,1080
    sdl.Init(sdl.INIT_VIDEO)
    Num,err :=sdl.GetNumVideoDisplays()
    if err!=nil {
        return err
    }
    var rect sdl.Rect
    rect,err = sdl.GetDisplayBounds(0)
    if err!=nil {
        return err
    }
    for i:=Num-1;i>=0;i--{
        Mod , _:=sdl.GetDisplayMode(i,0)
        if Mod.W ==info.winWidth && Mod.H==info.winHeight{
            rect,err = sdl.GetDisplayBounds(i)
            if err!=nil {
                return err
            }
            break
        }
    }
    sdlVars.window, err = sdl.CreateWindow(winTitle, rect.X, rect.Y,
        rect.W, rect.H, sdl.WINDOW_SHOWN)
    sdlVars.window.SetBordered(false)
    sdlVars.window.SetFullscreen(1)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Failed to create window: %s
", err)
        return err
    }
    sdlVars.renderer, err = sdl.CreateRenderer(sdlVars.window, -1, sdl.RENDERER_ACCELERATED)
    if err != nil {
        fmt.Fprintf(os.Stderr, "Failed to create renderer: %s
", err)
        return err
    }
    sdlVars.renderer.Clear()
    sdlVars.renderer.SetDrawColor(0, 0, 0, 255)
    sdlVars.renderer.FillRect(&sdl.Rect{0, 0, int32(info.winWidth), int32(info.winHeight)})
    sdlVars.renderer.Present()
    sdl.ShowCursor(0)
    return nil
}

This function handle events:

func (sdlVars *SDLstruct)HandleEvents()  {
    for sdlVars.event = sdl.PollEvent(); sdlVars.event != nil; sdlVars.event = sdl.PollEvent() {
        switch t := sdlVars.event.(type) {
        case *sdl.QuitEvent:
            sdlVars.Close = true
        }
    }
}

and this one closes everything:

func (sdlVars *SDLstruct)CloseSDL() (err error) {
    err =sdlVars.renderer.Destroy()
    if err!=nil{
        return err
    }
    err = sdlVars.window.Destroy()
    if err!=nil{
        return err
    }
    sdl.Quit()
    return nil
}

This is my Main function:

func main()  {
    var wg sync.WaitGroup
    SdlVars:= new(SDLstruct)
    wg.Add(1)
    go SdlVars.StartSDL()
    time.Sleep(time.Second*5)
    SdlVars.Close = true
    time.Sleep(time.Second*15)
}

In my Main function I tell it to start the sdl and after 5 seconds close everything and wait 15 seconds, but it doesn't close window.

  • 写回答

1条回答 默认 最新

  • duanjunao9348 2019-05-08 18:22
    关注

    Be careful as using SDL from multiple threads is not entirely trivial. Typically, your SDL loop must sit in the main thread. There is a good reason for that and it's because the event loop is part of the main thread and many of your objects are created and mutated on the main thread...or at least they should be.

    When you introduce multiple threads weird undefined and dangerous behavior could happen. This is why a good rule of thumb is to use runtime.LockOSThread to ensure the Go runtime doesn't pin your main goroutine to other threads and keeps it on the main thread.

    See this for more details: enter link description here

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料