Heim > Artikel > Backend-Entwicklung > Wie übergebe ich Funktionszeiger an C-Code mit Cgo in Go 1.6 und höher?
In Go 1.6 und höher gelten für Cgo strengere Regeln für die Übergabe Zeiger auf C-Code. Es ist nicht länger zulässig, einen Go-Zeiger zu übergeben, der auf einen Go-Speicher zeigt, der Go-Zeiger enthält.
Der folgende Go-Code zeigt, wie ein Funktionszeiger an C-Code übergeben wird:
<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>
Beim Ausführen dieses Codes wird ein Fehler erzeugt, da der Go-Speicher, auf den MyCallbackFunc zeigt, einen Go-Funktionszeiger (MyCallback) enthält.
To Um dies zu beheben, müssen wir einen Weg finden, den Funktionszeiger an C-Code zu übergeben, ohne die neuen Regeln zu verletzen.
Verwendung einer ID anstelle eines Zeigers
Ein Ansatz besteht darin, den Funktionszeiger in einer synchronisierten Datenstruktur zu speichern und anstelle eines direkten Zeigers eine ID an den C-Code zu übergeben. Auf diese Weise kann der C-Code die ID verwenden, um über die Datenstruktur auf den Funktionszeiger zuzugreifen.
Code mit ID-basierter Funktionszeigerübergabe
<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>
Das obige ist der detaillierte Inhalt vonWie übergebe ich Funktionszeiger an C-Code mit Cgo in Go 1.6 und höher?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!