Heim  >  Artikel  >  Backend-Entwicklung  >  Wie übergebe ich Funktionszeiger an C-Code mit cgo After Go v1.6?

Wie übergebe ich Funktionszeiger an C-Code mit cgo After Go v1.6?

Linda Hamilton
Linda HamiltonOriginal
2024-11-01 11:35:29177Durchsuche

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

Übergabe von Funktionszeigern an C-Code mit cgo

Vor Go v1.6 erlaubte cgo die Übergabe von Go-Zeigern an C-Code. Nach den in Version 1.6 implementierten Änderungen haben sich die Regeln für die Übergabe von Zeigern jedoch erheblich geändert. Diese Änderung machte die zuvor verwendete Methode zum Aufrufen dynamischer Go-Rückrufe aus C-Code unwirksam.

Problembeschreibung

Das Codebeispiel, einst ein Funktionsbeispiel für den Aufruf eines Go-Rückrufs von C, führt nun zu einem Laufzeitfehler:

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

Lösung

Unter den neuen CGO-Regeln darf Go-Code nur dann einen Go-Zeiger auf C übergeben, wenn der Der Go-Speicher, auf den er zeigt, enthält keine Go-Zeiger. Diese Einschränkung verhindert die Weitergabe von Zeigern an C-Code, wenn der Speicher, auf den verwiesen wird, Go-Funktions-/Methodenzeiger speichert.

Um diese Einschränkung zu überwinden, können mehrere Ansätze in Betracht gezogen werden. Eine gängige Lösung besteht darin, eine synchronisierte Datenstruktur zu speichern, die eine Entsprechung zwischen bestimmten IDs und den tatsächlichen Zeigern herstellt. Durch die Übergabe der ID an den C-Code anstelle des Zeigers wird die Einschränkung umgangen.

Ein aktualisiertes Codebeispiel, das diese Lösung zeigt:

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

Diese Lösung folgt der aktualisierten Wiki-Seite und bietet a Robuster Ansatz zur Übergabe von Funktionszeigern an C-Code innerhalb der aktuellen CGO-Einschränkungen.

Das obige ist der detaillierte Inhalt vonWie übergebe ich Funktionszeiger an C-Code mit cgo After Go v1.6?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn