Преамбула cgo

Преамбула cgo - это блок специальных комментариев, который располагается непосредственно перед импортом пакета "C". В преамбуле указываются директивы для компилятора C, флаги компиляции и линковки, а также объявления C-функций, которые будут доступны из Go-кода. Преамбула позволяет настраивать процесс сборки и интегрировать C-код в Go-программу.

Синтаксис

go// #include <stdio.h>
// #include <stdlib.h>
// #cgo CFLAGS: -O2
// #cgo LDFLAGS: -lm
import "C"

Преамбула состоит из строк, начинающихся с //, которые следуют сразу за ключевым словом package. Каждая строка преамбулы интерпретируется как директива для C-компилятора.

Пример

Давайте рассмотрим простой пример использования преамбулы для подключения заголовочного файла и объявления C-функции:

gopackage main

// #include <stdio.h>
// #include <stdlib.h>
// 
// void print_message(const char* msg) {
//   printf("C says: %s\n", msg);
// }
import "C"
import "unsafe"

func main() {
  msg := C.CString("Hello from Go!")
  C.print_message(msg)
  C.free(unsafe.Pointer(msg))
}

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

go"C says: Hello from Go!"

Пример

В следующем примере показано использование директив #cgo для указания флагов компиляции в зависимости от операционной системы:

gopackage main

// #cgo windows CFLAGS: -DWINDOWS
// #cgo linux CFLAGS: -DLINUX
// #cgo darwin CFLAGS: -DMACOS
// #include <stdlib.h>
// 
// int get_os_type() {
// #ifdef WINDOWS
//   return 1;
// #elif LINUX
//   return 2;
// #elif MACOS
//   return 3;
// #else
//   return 0;
// #endif
// }
import "C"
import "fmt"

func main() {
  osType := C.get_os_type()
  switch osType {
  case 1:
    fmt.Println("Running on Windows")
  case 2:
    fmt.Println("Running on Linux")
  case 3:
    fmt.Println("Running on macOS")
  default:
    fmt.Println("Unknown operating system")
  }
}

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

go"Running on Linux"

Пример

В этом примере показано использование преамбулы для подключения внешней библиотеки с помощью pkg-config:

gopackage main

// #cgo pkg-config: glib-2.0
// #include <glib.h>
// 
// char* get_version() {
//   return g_strdup(glib_check_version(NULL, NULL, NULL));
// }
import "C"
import (
  "fmt"
  "unsafe"
)

func main() {
  version := C.get_version()
  fmt.Printf("GLib version: %s\n", C.GoString(version))
  C.free(unsafe.Pointer(version))
}

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

go"GLib version: 2.70.0"

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

  • директиву #cgo CFLAGS,
    которая задает флаги для C-компилятора
  • директиву #cgo LDFLAGS,
    которая задает флаги для линковщика
  • директиву #cgo pkg-config,
    которая подключает библиотеки через pkg-config
  • функцию import "C",
    которая подключает C-код в Go-программу