Maison  >  Article  >  développement back-end  >  Comment transmettre des pointeurs de fonction au code C à l'aide de cgo After Go v1.6 ?

Comment transmettre des pointeurs de fonction au code C à l'aide de cgo After Go v1.6 ?

Linda Hamilton
Linda Hamiltonoriginal
2024-11-01 11:35:29177parcourir

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

Passer des pointeurs de fonction vers le code C à l'aide de cgo

Avant Go v1.6, cgo autorisait le passage de pointeurs Go vers le code C. Cependant, après les changements implémentés dans la v1.6, les règles de passage des pointeurs ont considérablement changé. Cette modification a rendu inefficace la méthode précédemment utilisée pour appeler des rappels Go dynamiques à partir du code C.

Description du problème

L'exemple de code, autrefois un exemple fonctionnel d'appel d'un rappel Go à partir de C, entraîne désormais une erreur d'exécution :

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

Solution

En vertu des nouvelles règles cgo, le code Go peut transmettre un pointeur Go vers C uniquement si le La mémoire Go vers laquelle elle pointe ne contient aucun pointeur Go. Cette restriction empêche de passer des pointeurs vers du code C si la mémoire pointée stocke des pointeurs de fonction/méthode Go.

Pour surmonter cette limitation, plusieurs approches peuvent être envisagées. Une solution courante consiste à stocker une structure de données synchronisée qui établit une correspondance entre des identifiants spécifiques et les pointeurs réels. En transmettant l'ID au code C au lieu du pointeur, la restriction est contournée.

Un exemple de code mis à jour présentant cette 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>

Cette solution suit la page wiki mise à jour, fournissant un approche robuste pour transmettre des pointeurs de fonction vers le code C dans le cadre des contraintes cgo actuelles.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn