背景
项目中免不了要使用c/c++的工程代码,因此使用cgo引入c的静态库也是不可避免(虽然官方要求尽量使用go构建你的项目,而不是偷巧的导入c代码,尽量保持go项目的纯粹,毕竟go和cgo是两码事)。
1 例子
github上有代码例子
1.1 windows上应用
windows下引用.lib形式的静态库是不可行的,go build的时候,会出现错误:
# command-line-arguments Warning: corrupt .drectve at end of def file
在运行的时候,会出现Segmentation fault错误。
但是可以通过MinWG版本的gcc/g++将代码编译成libxxx.a形式的静态库,即可完美引用,要求所生成的静态库名称必须以lib开头。
MinWG需要使用64位版本,下载地址
2 关于#cgo指令符
2.1 开发参数
#cgo指令符为c/c++编译器提供CFLAGS、CPPFLAGS、CXXFLAGS和LDFLAGS开发参数设置,同时也可以提供一些编译的约束,比如特定平台的参数:
/*
#cgo CFLAGS: -DPNG_DEBUG=1
#cgo amd64 386 CFLAGS: -DX86=1
#cgo LDFLAGS: -lpng
#include <png.h>
*/
import "C"
- CFLAGS 用来给c编译器提供开关,比如指定头文件的位置等。
- CXXFLAGS 用来给c++编译器提供开关。
- CPPFLAGS 用来给c预处理提供开关,对c/c++都有效。
- LDFLAGS 用来指定链接选项,比如链接库的位置,以及使用哪些链接库。
编译c文件的时候,一般会经过四个步骤: 预处理、编译、汇编和链接,开发参数可以起到如下作用:
// 预处理
$(CC) $(CPPFLAGS) $(CFLAGS) -E main.c -o main.i
// 编译
$(CC) $(CPPFLAGS) $(CFLAGS) -S main.i -o main.s
// 汇编,"-c"选项表示不执行链接步骤
$(CC) $(CPPFLAGS) $(CFLAGS) -c main.s -o main.o
// 也可以将前面的三个步骤合起来(预处理、编译、汇编)
$(CC) $(CPPFLAGS) $(CFLAGS) -c main.c -o main.o
// 然后将目标文件链接为最终的结果
$(CC) $(LDFLAGS) main.o -o main
// 也可以一次完成上面的步骤。
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) main.c -o main
2.2 ${SRCDIR}变量
${SRCDIR}变量用来指代原文件所在的文件夹的绝对路径,可以将预先编译好的静态库放在cgo项目的本地目录中,以便编译器可以正确找到库并链接。
以github的代码为例,如果代码目录在/gopath/src/go-static-link-example下面,则:
/*
#cgo LDFLAGS: -L${SRCDIR}/ -lsmth
#include "./smth.h"
*/
等价于:
/*
#cgo LDFLAGS: -L/gopath/src/go-static-link-example/ -lsmth
#include "./smth.h"
*/
参考
https://blog.csdn.net/jigetage/article/details/89435510
https://toutiao.io/posts/493728/app_preview