【问题标题】:Passing Go pointer to Cgo将 Go 指针传递给 Cgo
【发布时间】:2018-12-31 03:44:31
【问题描述】:

我一直在玩 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. 

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

【问题讨论】:

  • Values 是一个切片,其中包含一个指针。 Go slice 在 C 中并不是很有用,你打算用它做什么?
  • 好吧,我打算使用循环队列来存储回调函数中的事件,方法是使用 getuserpointer 检索它并避免全局变量,这就是我在 C 中至少这样做的方式
  • C 代码是否需要使用循环缓冲区,是否需要特定的结构?如果 C 代码完全使用该结构,它需要与 C 兼容。如果您需要通过一个不透明的结构,但需要在 Go 中实现它,也许使用包级别的变量,并将其封装在单独的包中够了。

标签: pointers go glfw cgo


【解决方案1】:

解决方案很简单。您必须将您提供给 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. 仅在您真正需要该概念的地方。

【讨论】:

    猜你喜欢
    • 2021-11-02
    • 2016-09-06
    • 1970-01-01
    • 2016-06-25
    • 2016-07-12
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 2018-12-20
    相关资源
    最近更新 更多