cgo构建引用c的静态链接库

December 09, 2023
测试
测试
测试
测试
3 分钟阅读

背景

项目中免不了要使用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

继续阅读

更多来自我们博客的帖子

如何安装 BuddyPress
由 测试 December 17, 2023
经过差不多一年的开发,BuddyPress 这个基于 WordPress Mu 的 SNS 插件正式版终于发布了。BuddyPress...
阅读更多
Filter如何工作
由 测试 December 17, 2023
在 web.xml...
阅读更多
如何理解CGAffineTransform
由 测试 December 17, 2023
CGAffineTransform A structure for holding an affine transformation matrix. ...
阅读更多