Recherche…
Appel de la fonction C à partir de Go
Cgo permet la création de packages Go qui appellent du code C.
Pour utiliser cgo
écrivez un code Go normal qui importe un pseudo-package "C". Le code Go peut alors faire référence à des types tels que C.int
ou des fonctions telles que C.Add
.
L'importation de "C" est immédiatement précédée d'un commentaire, ce commentaire, appelé préambule, est utilisé comme en-tête lors de la compilation des parties C du package.
Notez qu'il ne doit y avoir aucune ligne vide entre le commentaire cgo
et l'instruction import.
Notez que l' import "C"
ne peut pas être regroupée avec d'autres importations dans une instruction d'importation "factorisée" entre parenthèses. Vous devez écrire plusieurs instructions d'importation, comme:
import "C"
import "fmt"
Et c'est un bon style d'utiliser le relevé d'importation factorisé, pour d'autres importations, comme:
import "C"
import (
"fmt"
"math"
)
Exemple simple utilisant cgo
:
package main
//int Add(int a, int b){
// return a+b;
//}
import "C"
import "fmt"
func main() {
a := C.int(10)
b := C.int(20)
c := C.Add(a, b)
fmt.Println(c) // 30
}
Ensuite, go build
et exécutez le résultat:
30
Pour construire des paquets cgo
, utilisez simplement go build
ou go install
normalement. L' go tool
reconnaît l'importation spéciale "C"
et utilise automatiquement cgo
pour ces fichiers.
Fil C et Go dans toutes les directions
Appeler le code C de Go
package main
/*
// Everything in comments above the import "C" is C code and will be compiles with the GCC.
// Make sure you have a GCC installed.
int addInC(int a, int b) {
return a + b;
}
*/
import "C"
import "fmt"
func main() {
a := 3
b := 5
c := C.addInC(C.int(a), C.int(b))
fmt.Println("Add in C:", a, "+", b, "=", int(c))
}
Code d'appel de C de C
package main
/*
static inline int multiplyInGo(int a, int b) {
return go_multiply(a, b);
}
*/
import "C"
import (
"fmt"
)
func main() {
a := 3
b := 5
c := C.multiplyInGo(C.int(a), C.int(b))
fmt.Println("multiplyInGo:", a, "*", b, "=", int(c))
}
//export go_multiply
func go_multiply(a C.int, b C.int) C.int {
return a * b
}
Traiter les pointeurs de fonction
package main
/*
int go_multiply(int a, int b);
typedef int (*multiply_f)(int a, int b);
multiply_f multiply;
static inline init() {
multiply = go_multiply;
}
static inline int multiplyWithFp(int a, int b) {
return multiply(a, b);
}
*/
import "C"
import (
"fmt"
)
func main() {
a := 3
b := 5
C.init(); // OR:
C.multiply = C.multiply_f(go_multiply);
c := C.multiplyWithFp(C.int(a), C.int(b))
fmt.Println("multiplyInGo:", a, "+", b, "=", int(c))
}
//export go_multiply
func go_multiply(a C.int, b C.int) C.int {
return a * b
}
Types de conversion, structures d'accès et arithmétique de pointeur
De la documentation officielle Go:
// Go string to C string
// The C string is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func C.CString(string) *C.char
// Go []byte slice to C array
// The C array is allocated in the C heap using malloc.
// It is the caller's responsibility to arrange for it to be
// freed, such as by calling C.free (be sure to include stdlib.h
// if C.free is needed).
func C.CBytes([]byte) unsafe.Pointer
// C string to Go string
func C.GoString(*C.char) string
// C data with explicit length to Go string
func C.GoStringN(*C.char, C.int) string
// C data with explicit length to Go []byte
func C.GoBytes(unsafe.Pointer, C.int) []byte
Comment l'utiliser:
func go_handleData(data *C.uint8_t, length C.uint8_t) []byte {
return C.GoBytes(unsafe.Pointer(data), C.int(length))
}
// ...
goByteSlice := []byte {1, 2, 3}
goUnsafePointer := C.CBytes(goByteSlice)
cPointer := (*C.uint8_t)(goUnsafePointer)
// ...
func getPayload(packet *C.packet_t) []byte {
dataPtr := unsafe.Pointer(packet.data)
// Lets assume a 2 byte header before the payload.
payload := C.GoBytes(unsafe.Pointer(uintptr(dataPtr)+2), C.int(packet.dataLength-2))
return payload
}