I've been playing around with the GLFW bindings, and I'd like to pass a Queue structure to it, via glfw.SetUserPointer(...),
As such, I pass a it like this:
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))
But I get a runtime error,
panic: runtime error: cgo argument has Go pointer to Go pointer
I do some digging and it seems like... and I quote:
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.
But, my structure has no pointers in it, I'm confused :(
Solution is quite simple. You have to flatten what you provide to the C code. Rather than pass the circular queue, pass the data.
//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))
But the real problem is that you are trying to implement a complex data structure partially in C, partially in Go. Either implement the circula buffer