Python 简洁优美,开发效率高。Go 静态强类型、编译型、并发型,运行效率高。将复杂计算部分使用 Go 开发,编译成动态链接库,在 Python 中调用,能够提高开发效率和提高运算速度。

动态链接库

动态链接库文件是一种不可执行的二进制程序文件,它运行程序共享执行特殊任务所必需的代码和资源。

在 Windows 中动态链接库常以 .dll 结尾;在 Linux 系统中动态链接库常以 .so 结尾。

动态链接就是把一些经常会共用的程式码制作成 DLL 文件,当执行档呼叫到 DLL 档中的函数时,Windows 作业系统才会把 DLL 档载入记忆体内,DLL档本身的结构就是可执行档,当程式有需求时函数才进行链接。通过动态链接方式,记忆体浪费的情形可大幅降低。静态链接则是直接连结到执行档。DLL 的最初目的是节约应用程序所需的磁盘和内存空间。

Go 代码

这里给出一个简单的 Go 代码,内容如下,保存为 add.go 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import "C" //必须引入 C 库

import "fmt"

//加入下面注释代码,表示导出后,可以被 python 调用
//注意下面的注释不要写成 "// export xxx", 要写成 "//export xxx"
//否则无法调用

//export PrintDll
func PrintDll() {
fmt.Println("我来自 GO 动态链接库")
}

//export Add
func Add(a int, b int) int {
return a + b
}

func main() {
//必须加一个main函数,作为CGO编译的入口,无具体实现代码
}

编译称动态链接库文件

编译 add.go 源文件在不同的平台方法不同。下面分平台进行介绍。

Linux and Mac

一般 Linux 系统都自带 gcc软件,可以直接使用如下命令编译

1
go build -buildmode=c-shared -o add.so add.go

add.go 编译成 add.so

Windows

Windows 上编译需要安装软件 MinGW,这样就可以使用 gcc,编译命令如下

1
go build -buildmode=c-shared -o add.dll add.go

add.go 编译成 add.dll

编译再讨论

一般通过上面的方法编译得到的动态链接库会相对较大,这也是 Go 令人诟病的一个点。使用如下手段能够一定程度上减小编译后的文件大小。

1
go build -ldflags "-s -w" -buildmode=c-shared -o add.so add.go
  • -s 表示压缩;

  • -w 表示去掉调试信息。

Python 中调用动态链接库文件

在 Python 中调用编译后的动态链接库文件需要使用模块 ctypes,具体的方法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 测试 Python 调用 GO 语言写的代码
# 需要先将 GO 代码编译成动态链接库

from ctypes import cdll

lib = cdll.LoadLibrary("./add.so") # 这里指定编译后的动态链接库文件

# 调用 GO 语言的 Add 函数
result = lib.Add(100, 200)

print(result)

# 调用 GO 语言的 PrintDll 函数
lib.PrintDll()

上面代码可以直接在 jupyter notebook 中运行,也可以保存为 add.py 文件,然后在命令行执行:

1
time python add.py

运行后的结果如下:

1
2
3
300
我来自 GO 动态链接库
python add.py 0.03s user 0.01s system 105% cpu 0.040 totalib.PrintDll()

Python 调用 C 函数的方法参加我的另一篇博文:Python 调用 C 语言的函数.

参考文献

  1. Python调用Go语言编译的动态链接库-Python和Go语言混编

  2. golang 编译为dll 的方法_dodod2012的博客-CSDN博客_go编译dll

  3. Golang 编译成 DLL 文件