为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕码人2483693 2021-12-27 16:06:09
我正在使用 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 中的错误,但我正在运行最新的稳定版本(几天前安装)。如果这不是一个简单的修复,有人可以解释“为什么”会发生这种情况吗?
查看完整描述

3 回答

?
阿晨1998

TA贡献2037条经验 获得超6个赞

问题在于,当 C 代码存储 Go 指针(在这种情况下,指向回调函数的指针)时,垃圾收集器无法在 C 代码中跟踪该指针,并且可能会垃圾收集该指针指向的内存,如果没有Go 代码正在引用它。这将导致 C 代码在尝试访问该内存时崩溃。运行时只知道 C 代码保留了指针(这就是它会恐慌的原因),但它不知道 C 代码稍后将用它做什么以及将保留它多长时间。

为了避免这种情况,大多数库使用的技巧是在 Go 中也保持一个指针(例如在全局映射中),以确保内存免受垃圾收集器的影响。go-qml 也使用了这个技巧。这个技巧有效,但编译器和垃圾收集器不知道它确实有效,他们无法验证您没有犯错(例如删除 Go 指针,而 C 代码仍然有它的指针)。

在 Go 1.6 中,Go 开发人员决定对此非常严格,他们根本不再允许 C 代码保留 Go 指针。但是,如果您禁用此检查,则在这种情况下一切仍然有效,因为 go-qml 正确实现了该技巧(但是,将来可能会中断,例如,如果 go 实现了移动垃圾收集器)。

这是关于它的问题:https : //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 中实际上不是问题,因为它没有实现移动垃圾收集器,但是制定了规则以便以后可以实现。


查看完整回答
反对 回复 2021-12-27
?
明月笑刀无情

TA贡献1828条经验 获得超4个赞

如果你只是在玩,我建议尝试使用 go 1.5.3。Go 1.6 在使用 cgo 时引入了一组不同的内存指针约束,这是一个更具限制性的集合,并且有可能一些专为旧版本 go 设计的 go 包现在打破了一两个 go 规则。

如果是这种情况,让旧包与 go 1.6 一起工作,其中 C 被允许调用 go 闭包,可能更难修复。但我还没有这方面的第一手经验。


查看完整回答
反对 回复 2021-12-27
?
浮云间

TA贡献1829条经验 获得超4个赞

感谢这里的所有帮助。我写了一篇关于在 Go 中使用 QML 的初学者教程。可以在这里查看。如果我遇到更多错误并找到修复程序,我会不断更新它。感谢大家的帮助。QML/GO 是一个很棒的组合。

https://golog.co/blog/article/Using_Go_with_QML_part_1


查看完整回答
反对 回复 2021-12-27
  • 3 回答
  • 0 关注
  • 351 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信