在Go 1.6 及更高版本中,Cgo傳遞有更嚴格的規則指向C 代碼的指標。不再允許傳遞指向包含任何 Go 指標的 Go 記憶體的 Go 指標。
以下Go 程式碼示範如何將函數指標傳遞給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>
執行此程式碼時,會產生錯誤,因為MyCallbackFunc 指向的Go 記憶體中包含Go 函數指標(MyCallback)。
To為了解決這個問題,我們需要找到一種方法,在不違反新規則的情況下將函數指標傳遞給 C 程式碼。
使用 ID 代替指標
一種方法是將函數指標儲存在同步資料結構中,並將ID傳遞給C程式碼而不是直接指標。這樣,C 程式碼就可以使用 ID 透過資料結構存取函數指標。
基於 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>
以上是如何在 Go 1.6 及更高版本中使用 Cgo 將函數指標傳遞給 C 程式碼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!