将Go指针传递给Cgo

时间:2018-07-23 16:04:31

标签: pointers go glfw cgo

我一直在研究GLFW绑定,我想通过glfw.SetUserPointer(...)将Queue结构传递给它,

这样,我就这样传递了它:

type CircularQueue struct {
    Values      []interface{}
    Front, Rear int32
    Capacity    int32
}

func newCircularQueue(capacity int32) *CircularQueue {
    if capacity < 1 {
        log.Fatal("Capacity of Circular Queue Zero or Negative")
    }

    queue := &CircularQueue{Capacity: capacity}
    queue.Values = make([]interface{}, capacity)
    return queue
}

...
events := newCircularQueue(16)
window.SetUserPointer(unsafe.Pointer(events))

但是我遇到了运行时错误

panic: runtime error: cgo argument has Go pointer to Go pointer

我进行了一些挖掘,似乎...并且我引用:

Go code may pass a Go pointer to C provided the Go memory to which it 
points does not contain any Go pointers. The C code must preserve this 
property: it must not store any Go pointers in Go memory, even temporarily. 
When passing a pointer to a field in a struct, the Go memory in question is 
the memory occupied by the field, not the entire struct. When passing a 
pointer to an element in an array or slice, the Go memory in question is the 
entire array or the entire backing array of the slice. 

但是,我的结构中没有指针,我很困惑:(

1 个答案:

答案 0 :(得分:2)

解决方案非常简单。您必须弄平提供给C代码的内容。而不是传递循环队列,而是传递数据。

//C
int mysterious_c_func(const char* values, front int32_t, back int32_t, capacity int32_t);

// Go
type CircularQueue struct {
    Values      []char //this can't possibly work with interface.
    Front, Rear int32
    Capacity    int32
}
...
var q CircularQueue
data := (*C.char)(unsafe.Pointer(q.values))
C.mysterious_c_func(data, C.int(queue.Front), C.int(queue.Rear), C.int(queue.Capacity))

但是真正的问题是您试图部分地在C中,部分在Go中实现复杂的数据结构。要么实现循环缓冲区

  1. 使用两种语言,并允许从数组构造。
  2. 仅在您真正需要该概念的地方。