首頁  >  文章  >  後端開發  >  如何在 Go 1.6 及更高版本中使用 Cgo 將函數指標傳遞給 C 程式碼?

如何在 Go 1.6 及更高版本中使用 Cgo 將函數指標傳遞給 C 程式碼?

Linda Hamilton
Linda Hamilton原創
2024-10-30 17:46:31698瀏覽

How to Pass Function Pointers to C Code Using Cgo in Go 1.6 and Later?

使用Cgo 將函數指標傳遞給C 程式碼

Cgo 函數指標傳遞的變化

在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(&amp;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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn