使用 cgo 将函数指针传递给 C 代码
从 Go v1.6 开始,cgo 更改了将指针传递给 C 代码的规则。 Go wiki 中概述的从 C 代码调用动态 Go 回调的先前方法不再有效。
cgo 的新规则
cgo 现在禁止传递 Go 指针如果它们引用的内存本身包含任何 Go 指针,则指向 C。此限制在运行时强制执行,如果违反,则会导致程序崩溃。
克服限制
尽管有新的限制,但仍有多种方法可以将指针传输到 C 代码同时遵守强加的规则。一种常见的方法涉及存储在唯一 ID 和实际指针之间映射的同步数据结构。这样可以将 ID 传输到 C 代码,而不是直接指针。
代码解决方案
以下代码片段演示了该问题的解决方案:
<code class="go">package main import ( "fmt" "sync" ) // Declare a function to be invoked by C code. func MyCallback(x int) { fmt.Println("callback with", x) } func Example() { i := register(MyCallback) // Register the callback function and obtain its ID. C.CallMyFunction(C.int(i)) // Pass the ID to the C function. unregister(i) // Deregister the callback function. } // Data structures for registering and deregistering callbacks. var mu sync.Mutex var index int var fns = make(map[int]func(int)) // Register a callback function and return its ID. func register(fn func(int)) int { mu.Lock() defer mu.Unlock() index++ for fns[index] != nil { index++ } fns[index] = fn return index } // Return the callback function associated with a given ID. func lookup(i int) func(int) { mu.Lock() defer mu.Unlock() return fns[i] } // Deregister a callback function using its ID. func unregister(i int) { mu.Lock() defer mu.Unlock() delete(fns, i) } func main() { Example() }</code>
此代码符合 wiki 页面的更新指南,并提供了在新的 cgo 规则下将函数指针传递给 C 代码的可行解决方案。
以上是Go v1.6 发生更改后,如何使用 cgo 将函数指针传递给 Go 中的 C 代码?的详细内容。更多信息请关注PHP中文网其他相关文章!