Sök…
Cgo: Tutorials för första steg
Några exempel för att förstå arbetsflödet för att använda Go C-bindningar
Vad
I Go kan du ringa C-program och funktioner med hjälp av cgo . På så sätt kan du enkelt skapa C-bindningar till andra applikationer eller bibliotek som tillhandahåller C API.
Hur
Allt du behöver göra är att lägga till en import "C"
i början av ditt Go-program precis efter att du har inkluderat ditt C-program:
//#include <stdio.h> import "C"
Med föregående exempel kan du använda stdio
paketet i Go.
Om du behöver använda en app som finns i samma mapp använder du samma syntax än i C (med "
istället för <>
)
//#include "hello.c" import "C"
VIKTIGT : Lämna inte en ny linje mellan
include
ochimport "C"
uttalanden, så får du den här typen av fel vid build:
# command-line-arguments could not determine kind of name for C.Hello could not determine kind of name for C.sum
Exemplet
I den här mappen kan du hitta ett exempel på C-bindningar. Vi har två mycket enkla C-bibliotek som heter hello.c
:
//hello.c #include <stdio.h> void Hello(){ printf("Hello world\n"); }
Det skriver helt enkelt ut "hejvärld" i konsolen och sum.c
//sum.c #include <stdio.h> int sum(int a, int b) { return a + b; }
... som tar två argument och returnerar summan (skriv inte ut den).
Vi har ett main.go
program som kommer att använda dessa två filer. Först importerar vi dem som vi nämnde tidigare:
//main.go package main /* #include "hello.c" #include "sum.c" */ import "C"
Hej världen!
Nu är vi redo att använda C-programmen i vår Go-app. Låt oss först prova Hello-programmet:
//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 }
Kör nu main.go-programmet med hjälp av go run main.go
att få utskrift av C-programmet: "Hej värld!". Bra gjort!
Summan av ints
Låt oss göra det lite mer komplicerat genom att lägga till en funktion som sammanfattar sina två argument.
//sum.c #include <stdio.h> int sum(int a, int b) { return a + b; }
Och vi kommer att ringa det från vår tidigare Go-app.
//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 }
Ta en titt på "makeSum" -funktionen. Den får två int
parametrar som måste konverteras till C int
innan med hjälp av C.int
funktionen. Dessutom kommer samtalets återkomst att ge oss en int
och ett fel om något skulle gå fel. Vi måste skicka C-svar på ett Go-int med int()
.
Prova att köra vår go-app genom att använda go run main.go
$ go run main.go Hello world! Sum of 5 + 4 is 9
Generera en binär
Om du försöker en go build kan du få flera definitionsfel.
$ 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
Tricket är att referera till huvudfilen direkt när du använder go build
:
$ go build main.go $ ./main Hello world! Sum of 5 + 4 is 9
Kom ihåg att du kan ange ett namn på den binära filen genom att använda
-o
flaggago build -o my_c_binding main.go
Jag hoppas att du gillade den här tutorialen.