Zoeken…
C-functie aanroepen vanaf Go
Met Cgo kunnen Go-pakketten worden gemaakt die C-code aanroepen.
Om cgo
te gebruiken cgo
schrijft u de normale Go-code die een cgo
"C" importeert. De Go-code kan vervolgens verwijzen naar typen zoals C.int
of functies zoals C.Add
.
Het importeren van "C" wordt onmiddellijk voorafgegaan door een opmerking, die opmerking, de preambule genaamd, wordt gebruikt als een koptekst bij het compileren van de C-delen van het pakket.
Merk op dat er geen lege regels mogen zijn tussen de cgo
opmerking en de importverklaring.
Merk op dat import "C"
niet kan worden gegroepeerd met andere importen in een haakje, "factored" import statement. U moet meerdere importinstructies schrijven, zoals:
import "C"
import "fmt"
En het is een goede stijl om de factored importverklaring te gebruiken voor andere importen, zoals:
import "C"
import (
"fmt"
"math"
)
Eenvoudig voorbeeld met behulp van 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
}
Ga vervolgens go build
en voer het uit, output:
30
Om cgo
pakketten te bouwen, gebruikt u gewoon go build
of go install
zoals gewoonlijk. De go tool
herkent de speciale "C"
cgo
en gebruikt automatisch cgo
voor die bestanden.
Draad C en Go-code in alle richtingen
C-code aanroepen vanuit 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))
}
Bellen Go code van 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
}
Omgaan met functiewijzers
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
}
Converteer typen, toegangsstructuren en rekenkundige aanwijzer
Uit de officiële Go-documentatie:
// 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
Hoe te gebruiken:
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
}