cgo初步理解

C/C++经过几十年的发展,已经积累了庞大的软件资产,它们很多久经考验而且性能已经足够优化.Go语言必须能够站在C/C++这个巨人的肩膀之上,有了海量的C/C++软件资产兜底之后,我们才可以放心愉快地用Go语言编程.C语言作为一个通用语言,很多库会选择提供一个C兼容的API,然后用其他不同的编程语言实现.Go语言通过自带的一个叫CGO的工具来支持C语言函数调用,同时我们可以用Go语言导出C动态库接口给其它语言使用


cgo的价值

  1. 没有银弹, Go语言也不是银弹, 无法解决全部问题
  2. 通过CGO可以继承C/C++将近半个世纪的软件积累
  3. 通过CGO可以用Go给其它系统写C接口的共享库
  4. CGO是Go和其它语言直接通讯的桥梁

  • CGO 是一个保底的后备技术
  • CGO 是 Go 的替补技术

可能的cgo的场景

  • 通过OpenGL或OpenCL使用显卡的计算能力
  • 通过OpenCV来进行图像分析
  • 通过Go编写Python扩展
  • 通过Go编写移动应用

编写cgo程序

要使用cgo特性,需要事先安装c/c++构建工具链,例如Linux下的gcc,windows下的MinGW工具

如果在Go代码中出现了import “C”语句则表示使用了CGO特性,紧跟在这行语句前面的注释是一种特殊语法,里面包含的是正常的C语言代码.当确保CGO启用的情况下,还可以在当前目录中包含C/C++对应的源文件

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

/*
#include <stdio.h>

void printint(int v) {
printf("printint: %d\n", v);
}
*/
import "C"

func main() {
v := 42
C.printint(C.int(v))
}

该示例展示了cgo的基本用法:开头的注释包括了需要调用的C函数和相关的头文件,头文件被include之后里面的所有的C语言元素都会被加入到”C”这个虚拟的包中(import “C”语句必须单独一行,不能和其他导入语句一起写)

向C函数传递参数也很简单,就直接转化成对应C语言类型传递就可以

cgo语句

在import “C”语句前的注释中可以通过#cgo语句设置编译阶段和链接阶段的相关参数
编译阶段的参数主要用于定义相关宏和指定头文件检索路径
链接阶段的参数主要是指定库文件检索路径和要链接的库文件

1
2
3
4
// #cgo CFLAGS: -DPNG_DEBUG=1 -I./include
// #cgo LDFLAGS: -L/usr/local/lib -lpng
// #include <png.h>
import "C"

CFLAGS部分,-D部分定义了宏PNG_DEBUG,值为1,-I定义了头文件包含的检索目录
LDFLAGS部分,-L指定了链接时库文件检索目录,-l指定了链接时需要链接png库

小结

cgo为C语言和Go语言提供了双向通讯的桥梁,个人认为学好cgo对自己的能力提升用处很大

0%