Директива #cgo pkg-config
Директива #cgo pkg-config позволяет автоматически получать флаги компиляции и линковки для системных библиотек через утилиту pkg-config. В качестве параметра указывается имя пакета, для которого нужно получить настройки. Директива упрощает интеграцию с популярными библиотеками, такими как GTK, GLib, SDL и другими.
Синтаксис
// #cgo pkg-config: package-name
import "C"
Директива располагается в комментарии перед объявлением импорта C. При сборке пакета Go автоматически выполнит команду pkg-config --cflags package-name для получения флагов компилятора и pkg-config --libs package-name для флагов линковщика.
Пример со встроенной библиотекой
Давайте используем библиотеку libsqlite3 для работы с SQLite через pkg-config:
package main
/*
#cgo pkg-config: sqlite3
#include <sqlite3.h>
#include <stdlib.h>
*/
import "C"
import (
"fmt"
"unsafe"
)
func main() {
var db *C.sqlite3
path := C.CString(":memory:")
defer C.free(unsafe.Pointer(path))
result := C.sqlite3_open(path, &db)
if result != C.SQLITE_OK {
fmt.Println("Failed to open database")
return
}
defer C.sqlite3_close(db)
fmt.Println("Database opened successfully")
}
Пример с несколькими пакетами
Можно указать несколько пакетов через пробел. Тогда флаги будут объединены:
package main
/*
#cgo pkg-config: gtk+-3.0 glib-2.0
#include <gtk/gtk.h>
#include <glib.h>
*/
import "C"
import (
"fmt"
)
func main() {
version := C.gtk_get_major_version()
fmt.Printf("GTK version: %d\n", version)
}
Условная компиляция
Директиву можно комбинировать с условиями для разных платформ:
package main
/*
#cgo linux pkg-config: glib-2.0
#cgo darwin pkg-config: glib-2.0
#cgo windows pkg-config: glib-2.0
#include <glib.h>
*/
import "C"
import (
"fmt"
)
func main() {
major := C.glib_major_version()
minor := C.glib_minor_version()
micro := C.glib_micro_version()
fmt.Printf("GLib version: %d.%d.%d\n", major, minor, micro)
}
Обработка ошибок
Если пакет не найден в системе, сборка завершится с ошибкой. Рассмотрим обработку такой ситуации:
package main
/*
#cgo pkg-config: nonexistent-package
*/
import "C"
import (
"fmt"
)
func main() {
fmt.Println("This will fail to build")
}
Результат выполнения сборки:
"package nonexistent-package not found"
Смотрите также
-
директиву
#cgo CFLAGS,
которая позволяет задать флаги компилятора напрямую -
директиву
#cgo LDFLAGS,
которая позволяет задать флаги линковщика напрямую -
раздел
преамбулы cgo,
где можно размещать произвольный C-код -
раздел
импорта "C",
который обеспечивает связь между Go и C