CGO
C 语言作为一个通用语言,很多库会选择提供一个 C 兼容的 API,然后用其他不同的编程语言实现。Go 语言通过自带的一个叫 CGO 的工具来支持 C 语言函数调用,同时我们可以用 Go 语言导出 C 动态库接口给其它语言使用。
hello world程序
package main
import "C"
func main() {
println("hello cgo")
}
- 代码通过 import “C” 语句启用 CGO 特性,主函数只是通过 Go 内置的 println 函数输出字符串,其中并没有任何和 CGO 相关的代码。
- 虽然没有调用 CGO 的相关函数,但是 go build 命令会在编译和链接阶段启动 gcc 编译器,这已经是一个完整的 CGO 程序了。
动态链接库(dll,so文件)
-
Linux下的动态库以.so 结尾
-
Windows下的动态库以.dll结尾
Go语言打包成动态链接库文件
windows下需要安装gcc
mac,Linux自带gcc
go
package main
import "C" //必须引入C库
import "fmt"
//加入下面注释代码,表示导出,可以被python调用
//export PrintDll
func PrintDll() {
fmt.Println("我来自dll")
}
//
//export Sum
func Sum(a int, b int) int {
return a + b
}
func main() {
//必须加一个main函数,作为CGO编译的入口,无具体实现代码
}
编译:go build -buildmode=c-shared -o s1.so main.go
用main.go生成s1.so
go build -buildmode=c-shared -o s1.dll main.go
用main.go生成s1.dll
- 注释 //export PrintBye 和 //export Sum 在编译 动态库(dll ,so)的时候是必须的,说明了 动态库 需要输出的函数。注释和下面的函数名之间不能有空行。
- main函数必须写,没有执行代码,作为CGO编译的入口
- 必须引入C库(import “C”)
编译模式buildmode
模式 | 说明 |
---|---|
archive | 编译成二进制文件。一般是静态库文件。 xx.a |
c-archive | 编译成C归档文件。C可调用的静态库。xx.a。注意要编译成此类文件需要import C 并且要外部调用的函数要使用 “//export 函数名” 的方式在函数上方注释。否则函数默认不会被导出。 |
c-shared | 编译成C共享库。同样需要 import “C” 和在函数上方注释 // export xxx |
default | 对于有main包的直接编译成可执行文件。没有main包的,编译成.a文件 |
exe | 编译成window可执行程序 |
plugin | 将main包和依赖的包一起编译成go plugin。非main包忽略。【类似C的共享库或静态库。插件式开发使用 |
-
-o表示输出,s1.so 表示编译成so文件的名字,s1.go表示编译哪个go文件
-
“-s -w” 选项用于减小生成动态链接库的体积,-s 是压缩,-w 是去掉调试信息
go build -ldflags "-s -w" -o main.dll -buildmode=c-shared s1.go
py
from ctypes import cdll
lib = cdll.LoadLibrary('./s1.so')
# 调用go语言的Sum
result = lib.Sum(100, 200)
print(result)
# 调用go语言的PrintDll
lib.PrintDll()