首頁  >  文章  >  後端開發  >  Go v1.6 之後如何使用 cgo 將函數指標傳遞給 C 程式碼?

Go v1.6 之後如何使用 cgo 將函數指標傳遞給 C 程式碼?

Linda Hamilton
Linda Hamilton原創
2024-11-01 11:35:29177瀏覽

How to Pass Function Pointers to C Code Using cgo After Go v1.6?

使用 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中文網其他相關文章!

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