猿问

golang qml (go-qml) cgo 参数有指向 Go 指针的 Go 指针

我正在使用 qml 库来创建 UI。我正在尝试学习如何从 UI (qml) 传递信息然后“做某事”。如果 QML 只是一个 UI,它就可以工作。当我这样做时,我可以运行得很好:


func main() {

    if len(os.Args) != 2 {

        fmt.Fprintf(os.Stderr, "usage: %s <qml file>\n", os.Args[0])

        os.Exit(1)

    }

    if err := qml.Run(run); err != nil {

        fmt.Fprintf(os.Stderr, "error: %v\n", err)

        os.Exit(1)

    }

}


func run() error {

    engine := qml.NewEngine()


    engine.On("quit", func() { os.Exit(0) })


    component, err := engine.LoadFile(os.Args[1])

    if err != nil {

        return err

    }

    window := component.CreateWindow(nil)

    window.Show()

    window.Wait()

    return nil

}

但是,当我添加一些代码时,为了尝试从 UI 中“学习”一些东西,我得到了运行时错误:


恐慌:运行时错误:cgo 参数具有指向 Go 指针的 Go 指针


我添加的代码是:


window.On("visibleChanged", func(visible bool) {

    if (visible) {

            fmt.Println("Width:", window.Int("width"))

    }

})

我在 OSX El Capitan 上运行“go version go1.6 darwin/amd64”


任何想法为什么?谷歌暗示这是 Go 1.6 Beta 中的错误,但我正在运行最新的稳定版本(几天前安装)。


如果这不是一个简单的修复,有人可以解释“为什么”会发生这种情况吗?


慕码人2483693
浏览 422回答 3
3回答

阿晨1998

问题在于,当 C 代码存储 Go 指针(在这种情况下,指向回调函数的指针)时,垃圾收集器无法在 C 代码中跟踪该指针,并且可能会垃圾收集该指针指向的内存,如果没有Go 代码正在引用它。这将导致 C 代码在尝试访问该内存时崩溃。运行时只知道 C 代码保留了指针(这就是它会恐慌的原因),但它不知道 C 代码稍后将用它做什么以及将保留它多长时间。为了避免这种情况,大多数库使用的技巧是在 Go 中也保持一个指针(例如在全局映射中),以确保内存免受垃圾收集器的影响。go-qml 也使用了这个技巧。这个技巧有效,但编译器和垃圾收集器不知道它确实有效,他们无法验证您没有犯错(例如删除 Go 指针,而 C 代码仍然有它的指针)。在 Go 1.6 中,Go 开发人员决定对此非常严格,他们根本不再允许 C 代码保留 Go 指针。但是,如果您禁用此检查,则在这种情况下一切仍然有效,因为 go-qml 正确实现了该技巧(但是,将来可能会中断,例如,如果 go 实现了移动垃圾收集器)。这是关于它的问题:https&nbsp;:&nbsp;//github.com/go-qml/qml/issues/170旁注:在这种特定情况下,传递给 C 的是一个指向 an 的指针interface{},它本身包含一个指向该函数的指针。这就是为什么您会收到错误“cgo 参数具有指向 Go 指针的 Go 指针”的原因。不允许这样做的原因是在 C 调用期间更难以保护这些指针免受 GC 的影响,而且不值得,因此被禁止(https://github.com/golang/go/问题/12416#issuecomment-136473697)。然而,即使这被允许,代码仍然会违反关于 C 代码保留 Go 指针副本的规则。这在 Go 1.6 中实际上不是问题,因为它没有实现移动垃圾收集器,但是制定了规则以便以后可以实现。

明月笑刀无情

如果你只是在玩,我建议尝试使用 go 1.5.3。Go 1.6 在使用 cgo 时引入了一组不同的内存指针约束,这是一个更具限制性的集合,并且有可能一些专为旧版本 go 设计的 go 包现在打破了一两个 go 规则。如果是这种情况,让旧包与 go 1.6 一起工作,其中 C 被允许调用 go 闭包,可能更难修复。但我还没有这方面的第一手经验。

浮云间

感谢这里的所有帮助。我写了一篇关于在 Go 中使用 QML 的初学者教程。可以在这里查看。如果我遇到更多错误并找到修复程序,我会不断更新它。感谢大家的帮助。QML/GO 是一个很棒的组合。https://golog.co/blog/article/Using_Go_with_QML_part_1
随时随地看视频慕课网APP

相关分类

Go
我要回答