Starting from Go v1.6 cgo changed the rules of passing pointers to the C code golang/go#12416. The example of invoking a dynamic Go callback from C code from the wiki doesn\'t
It depends exactly what you need to do with the callback function - but a trick that might work is to not pass the Go function, but a pointer to a struct with the function on it that you want.
For example:
package main
import (
"fmt"
"unsafe"
)
/*
extern void go_callback_int(void*, int);
static inline void CallMyFunction(void* pfoo) {
go_callback_int(pfoo, 5);
}
*/
import "C"
//export go_callback_int
func go_callback_int(pfoo unsafe.Pointer, p1 C.int) {
foo := (*Test)(pfoo)
foo.cb(p1)
}
type Test struct {
}
func (s *Test) cb(x C.int) {
fmt.Println("callback with", x)
}
func main() {
data := &Test{}
C.CallMyFunction(unsafe.Pointer(&data))
}
Another option might be to use a global variable as you had in your example, and then forgo passing anything useful in the pointer to C.
Like this:
package main
import (
"fmt"
"unsafe"
)
/*
extern void go_callback_int(void*, int);
static inline void CallMyFunction(void* pfoo) {
go_callback_int(pfoo, 5);
}
*/
import "C"
//export go_callback_int
func go_callback_int(_ unsafe.Pointer, p1 C.int) {
MyCallbackFunc(p1)
}
func MyCallback(x C.int) {
fmt.Println("callback with", x)
}
// we store it in a global variable so that the garbage collector
// doesn't clean up the memory for any temporary variables created.
var MyCallbackFunc = MyCallback
func main() {
C.CallMyFunction(nil)
}
It possibly depends on what your C callback needs to do.
If neither of these work it might be possible to do some tricks with channels to send the value you need (and keep it in scope).