Pointers 将Go指针传递给Cgo

Pointers 将Go指针传递给Cgo,pointers,go,glfw,cgo,Pointers,Go,Glfw,Cgo,我一直在玩GLFW绑定,我想通过GLFW.SetUserPointer(…)向它传递一个队列结构 因此,我通过了一个类似这样的测试: type CircularQueue struct { Values []interface{} Front, Rear int32 Capacity int32 } func newCircularQueue(capacity int32) *CircularQueue { if capacity < 1

我一直在玩GLFW绑定,我想通过GLFW.SetUserPointer(…)向它传递一个队列结构

因此,我通过了一个类似这样的测试:

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))
我做了一些挖掘,看起来。。。我引述:

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. 

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

解决方案非常简单。你必须将你提供给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语言

  • 并允许从数组中构造
  • 只有在你真正需要这个概念的地方

  • Values
    是一个切片,它包含一个指针。Go切片在C中不是很有用,你打算用它做什么?我打算使用循环队列来存储回调函数中的事件,方法是用getuserpointer检索它,并避免全局变量,这就是我在C中的方法至少C代码需要使用循环b吗uffer,它需要一个特定的结构吗?如果C代码使用该结构,它需要与C兼容。如果您需要通过一个不透明的结构,但需要在Go中实现它,也许使用一个包级别的变量,并将其封装在一个单独的包中就足够了。
    //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))