Go v1.6から開始cgoはポインタをCコードgolang/go#12416に渡すルールを変更しました。 WikiからCコードから動的Goコールバックを呼び出す例は、もう動作しません。cgoを使用してCコードへのポインタを渡す
package main
import (
"fmt"
"unsafe"
)
/*
extern void go_callback_int(void* foo, int p1);
// normally you will have to define function or variables
// in another separate C file to avoid the multiple definition
// errors, however, using "static inline" is a nice workaround
// for simple functions like this one.
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()
}
出力は次のようになります。
panic: runtime error: cgo argument has Go pointer to Go pointer
今日これを行うための適切な方法は何ですか? uintptr_tに変換することで、言語からポインタを隠すようなハックがないことが好ましい。
新しいcgoルールの状態は次のようになっています。Go関数を渡すのではなく、関数の構造体へのポインタを渡すのではなく、あなたが示唆していることを理解している限り、 _Goコードは、それが指すGoメモリがGoポインタを含まないという条件で、GoポインタをCに渡すことができる。 さらに、ランタイムチェックを使用してルールを適用します。 –