Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Bagaimana untuk Menghantar Penunjuk Fungsi kepada Kod C Menggunakan Cgo dalam Go 1.6 dan Kemudian?

Bagaimana untuk Menghantar Penunjuk Fungsi kepada Kod C Menggunakan Cgo dalam Go 1.6 dan Kemudian?

Linda Hamilton
Linda Hamiltonasal
2024-10-30 17:46:31698semak imbas

How to Pass Function Pointers to C Code Using Cgo in Go 1.6 and Later?

Melalukan Penunjuk Fungsi ke Kod C Menggunakan Cgo

Perubahan dalam Lulus Penunjuk Fungsi Cgo

Dalam Go 1.6 dan lebih baru, Cgo mempunyai peraturan yang lebih ketat untuk lulus penunjuk kepada kod C. Ia tidak lagi dibenarkan untuk menghantar penuding Go yang menghala ke memori Go yang mengandungi sebarang penuding Go.

Contoh Kod

Kod Go berikut menunjukkan cara menghantar penuding fungsi kepada kod C:

<code class="go">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(&amp;MyCallbackFunc))
}

func main() {
    Example()
}</code>

Ralat dan Penyelesaian

Apabila menjalankan kod ini, ia menghasilkan ralat kerana memori Go yang ditunjuk oleh MyCallbackFunc mengandungi penuding fungsi Go (MyCallback).

Kepada menangani perkara ini, kita perlu mencari cara untuk menghantar penuding fungsi kepada kod C tanpa melanggar peraturan baharu.

Menggunakan ID Daripada Penunjuk

Satu pendekatan adalah untuk menyimpan penunjuk fungsi dalam struktur data yang disegerakkan dan menghantar ID kepada kod C dan bukannya penunjuk langsung. Dengan cara ini, kod C boleh menggunakan ID untuk mengakses penuding fungsi melalui struktur data.

Kod dengan Hantaran Penunjuk Fungsi Berasaskan ID

<code class="go">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)
}</code>

Atas ialah kandungan terperinci Bagaimana untuk Menghantar Penunjuk Fungsi kepada Kod C Menggunakan Cgo dalam Go 1.6 dan Kemudian?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn