Recherche…
Cgo: tutoriel Premiers pas
Quelques exemples pour comprendre le flux de travail de l'utilisation des liaisons Go C
Quelle
Dans Go, vous pouvez appeler les programmes et fonctions C en utilisant cgo . De cette façon, vous pouvez facilement créer des liaisons C vers d'autres applications ou bibliothèques fournissant une API C.
Comment
Tout ce que vous avez à faire est d'ajouter un import "C"
au début de votre programme Go juste après avoir inclus votre programme C:
//#include <stdio.h> import "C"
Avec l'exemple précédent, vous pouvez utiliser le package stdio
dans Go.
Si vous avez besoin d'utiliser une application qui se trouve dans votre même dossier, vous utilisez la même syntaxe que dans C (avec le "
au lieu de <>
)
//#include "hello.c" import "C"
IMPORTANT : Ne laissez pas de nouvelle ligne entre les instructions
import "C"
include
etimport "C"
ou vous obtiendrez ce type d'erreurs lors de la génération:
# command-line-arguments could not determine kind of name for C.Hello could not determine kind of name for C.sum
L'exemple
Dans ce dossier, vous pouvez trouver un exemple de liaisons C. Nous avons deux bibliothèques "C" très simples appelées hello.c
:
//hello.c #include <stdio.h> void Hello(){ printf("Hello world\n"); }
Cela imprime simplement "hello world" dans la console et sum.c
//sum.c #include <stdio.h> int sum(int a, int b) { return a + b; }
... qui prend 2 arguments et retourne sa somme (ne pas l'imprimer).
Nous avons un programme main.go
qui utilisera ces deux fichiers. Nous les importons d’abord comme nous l’avons déjà mentionné:
//main.go package main /* #include "hello.c" #include "sum.c" */ import "C"
Bonjour le monde!
Nous sommes maintenant prêts à utiliser les programmes C dans notre application Go. Essayons d'abord le programme Hello:
//main.go package main /* #include "hello.c" #include "sum.c" */ import "C" func main() { //Call to void function without params err := Hello() if err != nil { log.Fatal(err) } } //Hello is a C binding to the Hello World "C" program. As a Go user you could //use now the Hello function transparently without knowing that it is calling //a C function func Hello() error { _, err := C.Hello() //We ignore first result as it is a void function if err != nil { return errors.New("error calling Hello function: " + err.Error()) } return nil }
Maintenant, exécutez le programme main.go en utilisant go run main.go
pour obtenir l'impression du programme C: "Hello world!". Bien joué!
Somme des ints
Rendons-le un peu plus complexe en ajoutant une fonction qui résume ses deux arguments.
//sum.c #include <stdio.h> int sum(int a, int b) { return a + b; }
Et nous l'appellerons depuis notre précédente application Go.
//main.go package main /* #include "hello.c" #include "sum.c" */ import "C" import ( "errors" "fmt" "log" ) func main() { //Call to void function without params err := Hello() if err != nil { log.Fatal(err) } //Call to int function with two params res, err := makeSum(5, 4) if err != nil { log.Fatal(err) } fmt.Printf("Sum of 5 + 4 is %d\n", res) } //Hello is a C binding to the Hello World "C" program. As a Go user you could //use now the Hello function transparently without knowing that is calling a C //function func Hello() error { _, err := C.Hello() //We ignore first result as it is a void function if err != nil { return errors.New("error calling Hello function: " + err.Error()) } return nil } //makeSum also is a C binding to make a sum. As before it returns a result and //an error. Look that we had to pass the Int values to C.int values before using //the function and cast the result back to a Go int value func makeSum(a, b int) (int, error) { //Convert Go ints to C ints aC := C.int(a) bC := C.int(b) sum, err := C.sum(aC, bC) if err != nil { return 0, errors.New("error calling Sum function: " + err.Error()) } //Convert C.int result to Go int res := int(sum) return res, nil }
Regardez la fonction "makeSum". Il reçoit deux paramètres int
qui doivent être convertis en C int
avant en utilisant la fonction C.int
. De plus, le retour de l'appel nous donnera un C int
et une erreur en cas de problème. Nous devons convertir la réponse C en un int de Go en utilisant int()
.
Essayez de lancer notre application go en utilisant go run main.go
$ go run main.go Hello world! Sum of 5 + 4 is 9
Générer un binaire
Si vous essayez une construction, vous pourriez avoir plusieurs erreurs de définition.
$ go build # github.com/sayden/c-bindings /tmp/go-build329491076/github.com/sayden/c-bindings/_obj/hello.o: In function `Hello': ../../go/src/github.com/sayden/c-bindings/hello.c:5: multiple definition of `Hello' /tmp/go-build329491076/github.com/sayden/c-bindings/_obj/main.cgo2.o:/home/mariocaster/go/src/github.com/sayden/c-bindings/hello.c:5: first defined here /tmp/go-build329491076/github.com/sayden/c-bindings/_obj/sum.o: In function `sum': ../../go/src/github.com/sayden/c-bindings/sum.c:5: multiple definition of `sum` /tmp/go-build329491076/github.com/sayden/c-bindings/_obj/main.cgo2.o:/home/mariocaster/go/src/github.com/sayden/c-bindings/sum.c:5: first defined here collect2: error: ld returned 1 exit status
L'astuce consiste à se référer directement au fichier principal lors de l'utilisation de go build
:
$ go build main.go $ ./main Hello world! Sum of 5 + 4 is 9
Rappelez-vous que vous pouvez donner un nom au fichier binaire en utilisant
-o
flaggo build -o my_c_binding main.go
J'espère que vous avez apprécié ce tutoriel.