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와 실제 포인터 간의 대응을 설정하는 동기화된 데이터 구조를 저장하는 것이 포함됩니다. 포인터 대신 C 코드에 ID를 전달하면 제한이 우회됩니다.
이 솔루션을 보여주는 업데이트된 코드 샘플:
<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 중국어 웹사이트의 기타 관련 기사를 참조하세요!