Поиск…
Cgo: Учебное пособие по первым шагам
Некоторые примеры, чтобы понять рабочий процесс использования Go C Bindings
Какие
В Go вы можете вызывать программы и функции C с помощью cgo . Таким образом, вы можете легко создавать привязки C к другим приложениям или библиотекам, которые предоставляют C API.
Как
Все, что вам нужно сделать, это добавить import "C"
в начале вашей программы Go сразу после включения вашей программы на C:
//#include <stdio.h> import "C"
В предыдущем примере вы можете использовать пакет stdio
в Go.
Если вам нужно использовать приложение, находящееся в той же папке, вы используете тот же синтаксис, что и в C (вместо « <>
"
вместо <>
)
//#include "hello.c" import "C"
ВАЖНО : не оставляйте новую строку между операторами
include
иimport "C"
или вы получите этот тип ошибок при сборке:
# command-line-arguments could not determine kind of name for C.Hello could not determine kind of name for C.sum
Пример
В этой папке вы можете найти пример связок C. У нас есть две очень простые C "библиотеки", называемые hello.c
:
//hello.c #include <stdio.h> void Hello(){ printf("Hello world\n"); }
Это просто печатает «hello world» в консоли и sum.c
//sum.c #include <stdio.h> int sum(int a, int b) { return a + b; }
... который принимает 2 аргумента и возвращает свою сумму (не печатайте).
У нас есть программа main.go
которая будет использовать эти два файла. Сначала мы импортируем их, как мы упоминали ранее:
//main.go package main /* #include "hello.c" #include "sum.c" */ import "C"
Привет, мир!
Теперь мы готовы использовать программы C в нашем приложении Go. Сначала попробуем программу 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 }
Теперь запустите программу main.go, используя go run main.go
чтобы получить распечатку программы C: «Привет, мир!». Отлично сработано!
Сумма ints
Давайте сделаем это немного сложнее, добавив функцию, которая суммирует два своих аргумента.
//sum.c #include <stdio.h> int sum(int a, int b) { return a + b; }
И мы назовем это из нашего предыдущего 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 }
Взгляните на функцию «makeSum». Он получает два параметра int
которые необходимо преобразовать в C int
раньше, используя функцию C.int
. Кроме того, возврат вызова даст нам C int
и ошибку в случае, если что-то пошло не так. Нам нужно передать ответ C на int Go, используя int()
.
Попробуйте запустить наше приложение, используя go run main.go
$ go run main.go Hello world! Sum of 5 + 4 is 9
Создание двоичного кода
Если вы попробуете сборку go, вы можете получить несколько ошибок определения.
$ 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
Хитрость заключается в том, чтобы напрямую ссылаться на основной файл при использовании go build
:
$ go build main.go $ ./main Hello world! Sum of 5 + 4 is 9
Помните, что вы можете
go build -o my_c_binding main.go
имя двоичного файла, используя флаг-o
go build -o my_c_binding main.go
Надеюсь, вам понравился этот урок.