ホームページ  >  記事  >  バックエンド開発  >  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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。