Szukaj…
Cgo: samouczek Pierwsze kroki
Kilka przykładów, aby zrozumieć przepływ pracy przy użyciu powiązań Go C
Co
W Go możesz wywoływać programy i funkcje C za pomocą cgo . W ten sposób możesz łatwo tworzyć powiązania C z innymi aplikacjami lub bibliotekami, które zapewniają C API.
W jaki sposób
Wszystko, co musisz zrobić, to dodać import "C"
na początku programu Go tuż po dołączeniu programu C:
//#include <stdio.h> import "C"
W poprzednim przykładzie możesz użyć pakietu stdio
w Go.
Jeśli potrzebujesz użyć aplikacji, która znajduje się w tym samym folderze, używasz tej samej składni, co w C (z "
zamiast <>
)
//#include "hello.c" import "C"
WAŻNE : Nie zostawiaj nowego wiersza między instrukcjami
include
iimport "C"
, ponieważ pojawią się błędy tego typu podczas kompilacji:
# command-line-arguments could not determine kind of name for C.Hello could not determine kind of name for C.sum
Przykład
W tym folderze znajduje się przykład powiązań C. Mamy dwie bardzo proste „biblioteki” C o nazwie hello.c
:
//hello.c #include <stdio.h> void Hello(){ printf("Hello world\n"); }
To po prostu wypisuje „hello world” w konsoli i sum.c
//sum.c #include <stdio.h> int sum(int a, int b) { return a + b; }
... który pobiera 2 argumenty i zwraca jego sumę (nie drukuj).
Mamy program main.go
, który wykorzysta te dwa pliki. Najpierw importujemy je, jak wspomnieliśmy wcześniej:
//main.go package main /* #include "hello.c" #include "sum.c" */ import "C"
Witaj świecie!
Teraz jesteśmy gotowi do korzystania z programów C w naszej aplikacji Go. Najpierw wypróbujmy program 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 }
Teraz uruchom program main.go, używając polecenia go run main.go
aby uzyskać wydruk programu C: „Hello world!”. Dobra robota!
Suma ints
Zróbmy to nieco bardziej złożonym, dodając funkcję, która sumuje dwa argumenty.
//sum.c #include <stdio.h> int sum(int a, int b) { return a + b; }
Nazwiemy to z naszej poprzedniej aplikacji 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 }
Spójrz na funkcję „makeSum”. Otrzymuje dwa parametry int
, które należy wcześniej przekonwertować na C int
przy użyciu funkcji C.int
. Również zwrot połączenia da nam C int
i błąd na wypadek, gdyby coś poszło nie tak. Musimy rzutować odpowiedź C na int Go za pomocą int()
.
Spróbuj uruchomić naszą aplikację go, używając go run main.go
$ go run main.go Hello world! Sum of 5 + 4 is 9
Generowanie pliku binarnego
Jeśli spróbujesz kompilacji go, możesz otrzymać wiele błędów definicji.
$ 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
Sztuką jest odwoływanie się do głównego pliku bezpośrednio podczas korzystania z go build
:
$ go build main.go $ ./main Hello world! Sum of 5 + 4 is 9
Pamiętaj, że możesz podać nazwę pliku binarnego za pomocą opcji
-o
flaggo build -o my_c_binding main.go
Mam nadzieję, że podobał ci się ten samouczek.