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
}


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow