Ricerca…
Cgo: Primi passi tutorial
Alcuni esempi per capire il flusso di lavoro dell'utilizzo di Go C Bindings
Che cosa
In Go puoi chiamare programmi e funzioni C usando cgo . In questo modo è possibile creare facilmente associazioni C ad altre applicazioni o librerie che forniscono API C.
Come
Tutto quello che devi fare è aggiungere una import "C"
all'inizio del tuo programma Go subito dopo aver incluso il tuo programma C:
//#include <stdio.h> import "C"
Con l'esempio precedente puoi usare il pacchetto stdio
in Go.
Se hai bisogno di usare un'app che si trova nella tua stessa cartella, usi la stessa sintassi che in C (con "
invece di <>
)
//#include "hello.c" import "C"
IMPORTANTE : non lasciare una nuova riga tra le istruzioni di
include
e diimport "C"
o si otterrà questo tipo di errori durante la compilazione:
# command-line-arguments could not determine kind of name for C.Hello could not determine kind of name for C.sum
L'esempio
In questa cartella puoi trovare un esempio di associazioni C. Abbiamo due "librerie" C molto semplici chiamate hello.c
:
//hello.c #include <stdio.h> void Hello(){ printf("Hello world\n"); }
Questo semplicemente stampa "ciao mondo" nella console e sum.c
//sum.c #include <stdio.h> int sum(int a, int b) { return a + b; }
... che accetta 2 argomenti e restituisce la sua somma (non stamparla).
Abbiamo un programma main.go
che farà uso di questi due file. Per prima cosa li importiamo come abbiamo detto prima:
//main.go package main /* #include "hello.c" #include "sum.c" */ import "C"
Ciao mondo!
Ora siamo pronti per utilizzare i programmi C nella nostra app Go. Proviamo prima il programma 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 }
Ora esegui il programma main.go usando go run main.go
per ottenere la stampa del programma C: "Hello world!". Molto bene!
Somma di ints
Facciamo un po 'più complicato aggiungendo una funzione che riassume i suoi due argomenti.
//sum.c #include <stdio.h> int sum(int a, int b) { return a + b; }
E lo chiameremo dalla nostra precedente app 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 }
Dai un'occhiata alla funzione "makeSum". Riceve due parametri int
che devono essere convertiti in C int
prima usando la funzione C.int
. Inoltre, il ritorno della chiamata ci darà un C int
e un errore nel caso qualcosa sia andato storto. Abbiamo bisogno di lanciare la risposta C a int di Go utilizzando int()
.
Prova a eseguire la nostra app di go run main.go
utilizzando go run main.go
$ go run main.go Hello world! Sum of 5 + 4 is 9
Generare un binario
Se provi a fare una build potresti ottenere più errori di definizione.
$ 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
Il trucco è fare riferimento al file principale direttamente quando si usa go build
:
$ go build main.go $ ./main Hello world! Sum of 5 + 4 is 9
Ricorda che puoi fornire un nome al file binario usando
-o
flaggo build -o my_c_binding main.go
Spero che questo tutorial ti sia piaciuto.