Go 1.6 以降では、Cgo には受け渡しに関するより厳格なルールがあります。 C コードへのポインタ。 Go ポインターを含む Go メモリを指す Go ポインターを渡すことはできなくなりました。
次の Go コードは、関数ポインターを C コードに渡す方法を示しています。
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()
}
このコードを実行すると、MyCallbackFunc が指す Go メモリに Go 関数ポインター (MyCallback) が含まれているため、エラーが発生します。
To アドレスこのため、新しいルールに違反せずに関数ポインタを C コードに渡す方法を見つける必要があります。
ポインタの代わりに ID を使用する
1 つのアプローチは次のとおりです。関数ポインタを同期されたデータ構造に格納し、直接ポインタの代わりに ID を C コードに渡します。このように、C コードは ID を使用して、データ構造を通じて関数ポインターにアクセスできます。
ID ベースの関数ポインターを渡すコード
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)
}
免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。
Copyright© 2022 湘ICP备2022001581号-3