Директива import "C"

Директива import "C" используется для взаимодействия с C-кодом в Go-программах с помощью пакета cgo. Она позволяет вызывать функции из C-библиотек, использовать C-типы данных и работать с памятью, выделенной в C. Директива должна быть оформлена как обычный импорт, но располагаться в блоке комментария перед ним.

Синтаксис

go// #include <stdio.h>
import "C"

Перед директивой import "C" обязательно должен идти комментарий, содержащий C-код (например, включение заголовочных файлов). Между этим комментарием и директивой не должно быть пустых строк.

Пример

Рассмотрим базовый пример вызова функции printf из стандартной библиотеки C:

gopackage main

// #include <stdio.h>
import "C"

func main() {
  C.puts(C.CString("Hello from C!"))
}

Результат выполнения кода:

go"Hello from C!"

В этом примере мы импортируем псевдо-пакет C, который предоставляет доступ к функциям и типам из C. Функция C.puts принимает C-строку, созданную с помощью C.CString.

Работа с числами

В следующем примере показано, как передать целое число в C-функцию и получить результат обратно:

gopackage main

/*
  int add(int a, int b) {
    return a + b;
  }
*/
import "C"
import "fmt"

func main() {
  result := C.add(10, 20)
  fmt.Println(result)
}

Результат выполнения кода:

go30

В данном случае мы определили функцию add прямо в C-комментарии, а затем вызвали её из Go. Результат автоматически преобразуется в тип C.int, который совместим с Go-типом int.

Работа со строками

Для преобразования Go-строк в C-строки используется функция C.CString. Важно освобождать память после использования:

gopackage main

// #include <string.h>
import "C"
import "fmt"

func main() {
  goStr := "Hello, Go!"
  cStr := C.CString(goStr)
  defer C.free(unsafe.Pointer(cStr))

  length := C.strlen(cStr)
  fmt.Printf("String length: %d\n", length)
}

Результат выполнения кода:

go"String length: 10"

Здесь мы создаём C-строку с помощью C.CString, передаём её в функцию strlen и освобождаем память через C.free. Без освобождения памяти возникнет утечка.

Смотрите также

  • директиву preamble,
    которая задаёт C-код перед импортом
  • функцию C.CString,
    которая преобразует Go-строку в C-строку
  • функцию C.free,
    которая освобождает память, выделенную в C
  • функцию export,
    которая позволяет экспортировать Go-функции в C