我是一个相对新手。我一直在使用cgo和构建C api的接口。 C api使用已注册的回调函数和void*
cookie参数进行回调。
以下是一些例证我的问题的代码:
/*
void cb(void *cookie) {
callGo(cookie);
}
go_register_cb(void *ptr) {
register_cb(&cb, ptr);
}
*/
import "C"
和
import "C"
//export callGo
callGo(ptr unsafe.Pointer) {
x := (*MyStruct)(ptr)
x.doSomething()
}
func (x *MyStruct) Start() {
C.go_register_cb(unsafe.Pointer(x))
}
此代码导致Go指向Go指针的运行时错误。
我想我理解将Go指针保持在C-land中的基本含义,即在go垃圾收集器中不会考虑C-land引用,因此C可能最终使用过时的引用。
我无法将Go指针传递给本身包含Go指针的数据结构的特定要求更令人费解。对我来说唯一有意义的是,由于垃圾收集,Go中的指针可能会改变值(即,它们指向的地址)。是这种情况吗?
答案 0 :(得分:2)
在运行时动态检查用于在Go代码和C代码之间传递指针的这些规则。所以当你打破它们时会发生错误。
你的猜测是正确的。由于垃圾收集,允许更改地址(指针已更新)。
即使uintptr保存某个对象的地址,也就是垃圾 如果对象移动,收集器将不会更新该uintptr的值, uintptr也不会阻止对象被回收。
因此可能会因gc而移动物体。