cgo语句
在 import "C"
语句前的注释可以通过 #cgo
语句设置 编译阶段
和 链接阶段
的相关参数.
编译阶段的参数主要用于 定义相关的宏
和 指定头文件检索路径
.
链接阶段的参数主要是 指定库文件检索路径
和 要链接的库文件
.
// #cgo CFLAGS: -D PNG_DEBUG=1 -I ./include
// #cgo LDFLAGS: -L /usr/local/lib -l png
// #include <png.h>
import "C"
上面的代码中:
CFLAGS
部分, -D
部分定义了 PNG_DEBUG
, 值为 1
; -I
定义了头文件包含的检索目录.
LDFLAGS
部分, -L
指定了链接时文件检索目录, -l
指定了链接时需要链接 png
库.
因为 C/C++ 遗留的问题, C 头文件检索目录可以是相对目录, 但是 库文件检索目录
则需要是绝对路径.
在库文件的检索目录中可以通过 ${SRCDIR}
变量表示当前包含目录的绝对路径:
// #cgo LDFLAGS: -L ${SRCDIR}/libs -l foo
上面的代码在链接时将被展开为:
// #cgo LDFLAGS: -L /go/src/foo/libs -l foo
#cgo
语句主要影响 CFLAGS
, CPPFLAGS
, CXXFLAGS
, FFLAGS
, LDFLAGS
这几个编译器环境变量.
LDFLAGS
用于设置链接阶段的参数.
CFLAGS
, CXXFLAGS
,CPPFLAGS
, FFLAGS
这几个变量用于改变编译阶段的构建参数.
对于在cgo环境混合使用C和C++的用户来说, 可能有三种不同的编译选项: 其中 CFLAGS
对应 C 语言特有的编译选项,
CXXFLAGS
对应是 C++ 特有的编译选项, CPPFLAGS
则对应 C 和 C++ 共有的编译选项.
但是在链接阶段, C 和 C++的链接选项是通用的, 因此这个时候已经不再有C和C++语言的区别, 它们的目标文件的类型是相同的.
#cgo
指令还支持条件选择, 当满足某个操作系统或某个CPU架构类型时类型时后面的编译或链接选项生效.
条件选择:
// #cgo windows CFLAGS: -D X86=1
// #cgo !windows LDFLAGS: -l math
宏定义案例:
package main
/*
#cgo windows CFLAGS: -D CGO_OS_WINDOWS=1
#cgo darwin CFLAGS: -D CGO_OS_DRWIN=1
#cgo linux CFLAGS: -D CGO_OS_LINUX=1
#if defined(CGO_OS_WINDOWS)
const char* os = "windows";
#elif defined(CGO_OS_DARWIN)
const char* os = "darwin";
#elif defined(CGO_OS_LINUX)
const char* os = "linux";
#else
const char* os = "unknown";
#endif
*/
import "C"
func main() {
print(C.GoString(C.os))
}
注意:
1.在链接C库的使用, 不支持条件选择. 并且CGO参数有严格的格式
#cgo CFLAGS:...
或者#cgo LDFLAGS: ...
, 即#cgo
和 参数(CFLAGS
,LDFLAGS
)2.对于C语言库(
.h
文件定义内容 和.c
文件实现.h
的定义), 在CGO当中引用.h
文件, 必须采用动态库/静态库
链接的方式, 否则可能无法编译通过.