Home  >  Article  >  Backend Development  >  How to Pass Function Pointers to C Code Using cgo After Go v1.6?

How to Pass Function Pointers to C Code Using cgo After Go v1.6?

Linda Hamilton
Linda HamiltonOriginal
2024-11-01 11:35:29184browse

How to Pass Function Pointers to C Code Using cgo After Go v1.6?

Passing Function Pointers to C Code Using cgo

Prior to Go v1.6, cgo allowed the passing of Go pointers to C code. However, after the changes implemented in v1.6, the rules for passing pointers changed significantly. This alteration rendered the previously used method for invoking dynamic Go callbacks from C code ineffective.

Problem Description

The code sample, once a functional example of invoking a Go callback from C, now results in a runtime error:

panic: runtime error: cgo argument has Go pointer to Go pointer

Solution

Under the new cgo rules, Go code may pass a Go pointer to C only if the Go memory it points to does not contain any Go pointers. This restriction prevents passing pointers to C code if the pointed memory stores Go function/method pointers.

To overcome this limitation, several approaches can be considered. A common solution involves storing a synchronized data structure that establishes a correspondence between specific IDs and the actual pointers. By passing the ID to C code instead of the pointer, the restriction is bypassed.

An updated code sample showcasing this solution:

<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>

This solution follows the updated wiki page, providing a robust approach to passing function pointers to C code within the current cgo constraints.

The above is the detailed content of How to Pass Function Pointers to C Code Using cgo After Go v1.6?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn