Passing Function Pointers to C Code Using cgo
Prior to Go v1.6, cgo allowed the passing of Go pointers to C code. However, after the changes implemented in v1.6, the rules for passing pointers changed significantly. This alteration rendered the previously used method for invoking dynamic Go callbacks from C code ineffective.
Problem Description
The code sample, once a functional example of invoking a Go callback from C, now results in a runtime error:
panic: runtime error: cgo argument has Go pointer to Go pointer
Solution
Under the new cgo rules, Go code may pass a Go pointer to C only if the Go memory it points to does not contain any Go pointers. This restriction prevents passing pointers to C code if the pointed memory stores Go function/method pointers.
To overcome this limitation, several approaches can be considered. A common solution involves storing a synchronized data structure that establishes a correspondence between specific IDs and the actual pointers. By passing the ID to C code instead of the pointer, the restriction is bypassed.
An updated code sample showcasing this solution:
<code class="go">package gocallback import ( "fmt" "sync" ) /* extern void go_callback_int(int foo, int p1); */ import "C" var mu sync.Mutex var index int var fns = make(map[int]func(C.int)) func register(fn func(C.int)) int { mu.Lock() defer mu.Unlock() index++ for fns[index] != nil { index++ } fns[index] = fn return index } func lookup(i int) func(C.int) { mu.Lock() defer mu.Unlock() return fns[i] } func unregister(i int) { mu.Lock() defer mu.Unlock() delete(fns, i) } //export go_callback_int func go_callback_int(foo C.int, p1 C.int) { fn := lookup(int(foo)) fn(p1) } func MyCallback(x C.int) { fmt.Println("callback with", x) } func Example() { i := register(MyCallback) C.go_callback_int(C.int(i), 5) unregister(i) } func main() { Example() }</code>
This solution follows the updated wiki page, providing a robust approach to passing function pointers to C code within the current cgo constraints.
The above is the detailed content of How to Pass Function Pointers to C Code Using cgo After Go v1.6?. For more information, please follow other related articles on the PHP Chinese website!