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
}


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow