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(&MyCallbackFunc)) } func main() { Example() }</code>
MyCallbackFunc が指す Go メモリには Go 関数ポインター (MyCallback) が含まれているため、このコードを実行するとエラーが発生します。
Toこれに対処するには、新しいルールに違反せずに関数ポインタを C コードに渡す方法を見つける必要があります。
ポインタの代わりに ID を使用する
1 つのアプローチこれは、関数ポインタを同期されたデータ構造に格納し、直接ポインタの代わりに 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 中国語 Web サイトの他の関連記事を参照してください。