Go语言高级编程

324课时
1.4K学过
8分

2. 第2章 CGO编程

引言

2.1 快速入门

2.1.1 最简CGO程序

2.1.2 基于C标准库函数输出字符串

2.1.3 使用自己的C函数

2.1.4 C代码的模块化

2.1.5 用Go重新实现C函数

2.1.6 面向C接口的Go编程

2.2 CGO基础

2.2.1 import "C"语句

2.2.2 #cgo语句

2.2.3 build tag 条件编译

2.3 类型转换

2.3.1 数值类型

2.3.2 Go 字符串和切片

2.3.3 结构体、联合、枚举类型

2.3.4 数组、字符串和切片

2.3.5 指针间的转换

2.3.6 数值和指针的转换

2.3.7 切片间的转换

2.4 函数调用

2.4.1 Go调用C函数

2.4.2 C函数的返回值

2.4.3 void函数的返回值

2.4.4 C调用Go导出函数

2.5 内部机制

2.5.1 CGO生成的中间文件

2.5.2 Go调用C函数

2.5.3 C调用Go函数

2.6 实战: 封装qsort

2.6.1 认识qsort函数

2.6.2 将qsort函数从Go包导出

2.6.3 改进:闭包函数作为比较函数

2.6.4 改进:消除用户对unsafe包的依赖

2.7 CGO内存模型

2.7.1 Go访问C内存

2.7.2 C临时访问传入的Go内存

2.7.3 C长期持有Go指针对象

2.7.4 导出C函数不能返回Go内存

2.8 C++ 类包装

2.8.1 C++ 类到 Go 语言对象

2.8.1.1 准备一个 C++ 类

2.8.1.2 用纯C函数接口封装 C++ 类

2.8.1.3 将纯C接口函数转为Go函数

2.8.1.4 包装为Go对象

2.8.2 Go 语言对象到 C++ 类

2.8.2.1 构造一个Go对象

2.8.2.2 导出C接口

2.8.2.3 封装C++对象

2.8.2.4 封装C++对象改进

2.8.3 彻底解放C++的this指针

2.9 静态库和动态库

2.9.1 使用C静态库

2.9.2 使用C动态库

2.9.3 导出C静态库

2.9.4 导出C动态库

2.9.5 导出非main包的函数

2.10 编译和链接参数

2.10.1 编译参数:CFLAGS/CPPFLAGS/CXXFLAGS

2.10.2 链接参数:LDFLAGS

2.10.3 pkg-config

2.10.4 go get 链

2.10.5 多个非main包中导出C函数

课程评价 (0)

请对课程作出评价:
0/300

学员评价

暂无精选评价
15分钟

2.10.3 pkg-config

为不同C/C++库提供编译和链接参数是一项非常繁琐的工作,因此cgo提供了对应pkg-config工具的支持。 我们可以通过#cgo pkg-config xxx命令来生成xxx库需要的编译和链接参数,其底层通过调用 pkg-config xxx --cflags生成编译参数,通过pkg-config xxx --libs命令生成链接参数。 需要注意的是pkg-config工具生成的编译和链接参数是C/C++公用的,无法做更细的区分。

pkg-config工具虽然方便,但是有很多非标准的C/C++库并没有实现对其支持。 这时候我们可以手工为pkg-config工具创建对应库的编译和链接参数实现支持。

比如有一个名为xxx的C/C++库,我们可以手工创建/usr/local/lib/pkgconfig/xxx.bc文件:

Name: xxx
Cflags:-I/usr/local/include
Libs:-L/usr/local/lib –lxxx2

其中Name是库的名字,Cflags和Libs行分别对应xxx使用库需要的编译和链接参数。如果bc文件在其它目录, 可以通过PKG_CONFIG_PATH环境变量指定pkg-config工具的检索目录。

而对应cgo来说,我们甚至可以通过PKG_CONFIG 环境变量可指定自定义的pkg-config程序。 如果是自己实现CGO专用的pkg-config程序,只要处理--cflags--libs两个参数即可。

下面的程序是macos系统下生成Python3的编译和链接参数:

// py3-config.go
func main() {
	for _, s := range os.Args {
		if s == "--cflags" {
			out, _ := exec.Command("python3-config", "--cflags").CombinedOutput()
			out = bytes.Replace(out, []byte("-arch"), []byte{}, -1)
			out = bytes.Replace(out, []byte("i386"), []byte{}, -1)
			out = bytes.Replace(out, []byte("x86_64"), []byte{}, -1)
			fmt.Print(string(out))
			return
		}
		if s == "--libs" {
			out, _ := exec.Command("python3-config", "--ldflags").CombinedOutput()
			fmt.Print(string(out))
			return
		}
	}
}

然后通过以下命令构建并使用自定义的pkg-config工具:

$ go build -o py3-config py3-config.go
$ PKG_CONFIG=./py3-config go build -buildmode=c-shared -o gopkg.so main.go

具体的细节可以参考Go实现Python模块章节。