使用 cgo 將函數指標傳遞給 C 程式碼
在 Go v1.6 之前,cgo 允許將 Go 指標傳遞給 C 程式碼。然而,在 v1.6 實現變更後,傳遞指標的規則發生了顯著變化。此變更使得先前從 C 程式碼呼叫動態 Go 回呼的方法無效。
問題描述
程式碼範例,曾經是呼叫Go 回呼的功能範例來自C,現在會導致執行階段錯誤:
panic: runtime error: cgo argument has Go pointer to Go pointer
解
在新的cgo 規則下,Go 程式碼可以只在以下情況下將Go 指標傳遞給C:它指向的Go記憶體不包含任何Go指標。如果指向的記憶體儲存 Go 函數/方法指針,此限制會阻止將指針傳遞給 C 程式碼。
要克服此限制,可以考慮多種方法。常見的解決方案涉及儲存同步資料結構,該資料結構在特定 ID 和實際指標之間建立對應關係。透過將 ID 傳遞給 C 代碼而不是指針,可以繞過限制。
展示此解決方案的更新程式碼範例:
<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>
此解決方案遵循更新的wiki 頁面,提供了在當前cgo 約束內將函數指標傳遞給C 程式碼的穩健方法。
以上是Go v1.6 之後如何使用 cgo 將函數指標傳遞給 C 程式碼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!