Maison > Article > développement back-end > Comment transmettre des pointeurs de fonction au code C à l'aide de Cgo dans Go 1.6 et versions ultérieures ?
Dans Go 1.6 et versions ultérieures, Cgo a des règles plus strictes pour le passage pointeurs vers le code C. Il n'est plus autorisé de transmettre un pointeur Go qui pointe vers la mémoire Go contenant des pointeurs Go.
Le code Go suivant montre comment passer un pointeur de fonction vers le code C :
<code class="go">import ( "fmt" "unsafe" ) /* extern void go_callback_int(void* foo, int p1); 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 := *(*func(C.int))(pfoo) foo(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 Example() { C.CallMyFunction(unsafe.Pointer(&MyCallbackFunc)) } func main() { Example() }</code>
Lors de l'exécution de ce code, il produit une erreur car la mémoire Go pointée par MyCallbackFunc contient un pointeur de fonction Go (MyCallback).
À Pour résoudre ce problème, nous devons trouver un moyen de transmettre le pointeur de fonction au code C sans enfreindre les nouvelles règles.
Utiliser un identifiant au lieu d'un pointeur
Une approche consiste à stocker le pointeur de fonction dans une structure de données synchronisée et à transmettre un identifiant au code C au lieu d'un pointeur direct. De cette façon, le code C peut utiliser l'ID pour accéder au pointeur de fonction via la structure de données.
Code avec passage du pointeur de fonction basé sur l'ID
<code class="go">package gocallback import ( "fmt" "sync" ) /* extern void go_callback_int(int foo, int p1); static inline void CallMyFunction(int foo) { go_callback_int(foo, 5); } */ import "C" //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.CallMyFunction(C.int(i)) unregister(i) } 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) }</code>
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!