Saya mencoba membuat objek statis yang ditulis dalam antarmuka Pergi dengan program C (katakanlah, modul kernel atau sesuatu).
Saya telah menemukan dokumentasi tentang pemanggilan fungsi C dari Go, tetapi saya belum menemukan banyak tentang bagaimana cara sebaliknya. Apa yang saya temukan adalah mungkin, tetapi rumit.
Inilah yang saya temukan:
Posting blog tentang panggilan balik antara C dan Go
Adakah yang punya pengalaman dengan ini? Singkatnya, saya mencoba membuat modul PAM yang ditulis seluruhnya dalam Go.
c
shared-libraries
go
dynamic-linking
hajar
sumber
sumber
Jawaban:
Anda dapat memanggil kode Go dari C. itu adalah proposisi yang membingungkan.
Prosesnya diuraikan dalam posting blog yang Anda tautkan. Tapi saya bisa melihat bagaimana itu tidak terlalu membantu. Berikut ini cuplikan singkat tanpa bit yang tidak perlu. Seharusnya hal-hal sedikit lebih jelas.
Urutan semua hal disebut adalah sebagai berikut:
Kunci untuk diingat di sini adalah bahwa fungsi panggilan balik harus ditandai dengan
//export
komentar di sisi Go dan sepertiextern
di sisi C. Ini berarti bahwa setiap panggilan balik yang ingin Anda gunakan, harus ditentukan di dalam paket Anda.Untuk memungkinkan pengguna paket Anda untuk menyediakan fungsi panggilan balik khusus, kami menggunakan pendekatan yang sama persis seperti di atas, tetapi kami menyediakan penangan kustom pengguna (yang hanya merupakan fungsi Go biasa) sebagai parameter yang diteruskan ke C sisi sebagai
void*
. Ini kemudian diterima oleh penelepon balik dalam paket kami dan dipanggil.Mari kita gunakan contoh yang lebih maju yang saat ini saya kerjakan. Dalam hal ini, kami memiliki fungsi C yang melakukan tugas yang cukup berat: Ini membaca daftar file dari perangkat USB. Ini bisa memakan waktu cukup lama, jadi kami ingin aplikasi kami diberitahu tentang perkembangannya. Kita dapat melakukan ini dengan mengirimkan pointer fungsi yang kita tetapkan dalam program kita. Ini hanya menampilkan beberapa info kemajuan kepada pengguna setiap kali dipanggil. Karena memiliki tanda tangan yang terkenal, kita dapat menetapkan jenisnya sendiri:
Handler ini mengambil beberapa info kemajuan (jumlah file yang diterima saat ini dan jumlah total file) bersama dengan nilai antarmuka {} yang dapat menampung apa saja yang dibutuhkan pengguna untuk dipegang.
Sekarang kita perlu menulis pipa C dan Go untuk memungkinkan kita menggunakan penangan ini. Untungnya fungsi C yang ingin saya panggil dari pustaka memungkinkan kita untuk memasukkan data tipe userdata
void*
. Ini berarti dapat menyimpan apa pun yang kita inginkan, tidak ada pertanyaan yang diajukan dan kita akan mendapatkannya kembali ke Dunia Go apa adanya. Untuk membuat semua ini berfungsi, kami tidak memanggil fungsi pustaka dari Go secara langsung, tetapi kami membuat pembungkus C untuk itu yang akan kami beri namagoGetFiles()
. Ini pembungkus ini yang benar-benar memasok panggilan balik Go kami ke perpustakaan C, bersama dengan objek data pengguna.Perhatikan bahwa
goGetFiles()
fungsi tidak mengambil pointer fungsi untuk panggilan balik sebagai parameter. Alih-alih, panggilan balik yang diberikan pengguna kami dikemas dalam struct khusus yang berisi nilai data pengguna itu sendiri. Kami meneruskan inigoGetFiles()
sebagai parameter data pengguna.Itu saja untuk binding C kami. Kode pengguna sekarang sangat mudah:
Ini semua terlihat jauh lebih rumit daripada itu. Pesanan panggilan tidak berubah dibandingkan dengan contoh kami sebelumnya, tetapi kami mendapatkan dua panggilan tambahan di akhir rantai:
Urutannya adalah sebagai berikut:
sumber
Itu bukan proposisi yang membingungkan jika Anda menggunakan gccgo. Ini berfungsi di sini:
foo.go
bar.c
Makefile
sumber
go package main func Add(a, b string) int { return a + b }
saya mendapatkan kesalahan "undefined _go_string_plus"cgo
dango
bukangccgo
. Lihat golang.org/cmd/cgo . Ketika itu dikatakan, sangat mungkin untuk menggunakan tipe "string" dalam file .go dan mengubah file .c Anda untuk memasukkan__go_string_plus
fungsi. Ini berfungsi: ix.io/dZBJawabannya telah berubah dengan rilis Go 1.5
Pertanyaan SO ini yang saya tanyakan beberapa waktu lalu membahas masalah ini lagi mengingat 1.5 kemampuan yang ditambahkan
Menggunakan kode Go dalam proyek C yang ada
sumber
Sejauh yang saya ketahui tidak mungkin:
sumber: https://github.com/golang/go/wiki/cgo
sumber