前言
我们可以使用Go生成Python的动态链接库,这样就可以在Python中调用Go代码了,会极大的简化代码量。目前我用Go做了一个与匹配命令有关的一个函数,需要给我工作中别的使用python的小伙伴提供一个可在python直接调用的程序,python目前没有办法直接调用go的代码,需要先利用cgo将go的代码先转换一下,才能在python中调用。第一次做这个,跌跌撞撞遇到很多问题,不论是安装C的编译器还是转换数据类型等等等等(我感觉我遇上了所能遇见的各种问题…我做了很多个小demo最终一步步找到问题并解决),但是最终在python中能够调用go代码的那一刻,我露出了慈祥而又满足而又欣慰而又愉悦而又诡异的笑容😀。
使用环境介绍
- OS:window10
- Go:1.15.3
- python:3.9
处理过程
// export 函数名mainimport "C"gcc -v
go build -buildmode=c-shared -o dll文件或者so文件 go源文件
我的执行结果为:
目前没有报错,继续往下~
就开始了我坎坷的python调用go代码之旅!!!
我在python中写了简单的调用代码:
#!/user/bin/env python3
# -*- coding: utf-8 -*-
import ctypes
lib = ctypes.CDLL('./matchCommand.so')
str = lib.matchCommand("Linux", "factor --version")
print(str)
发现可以进入我的go文件,但是无法进入我的方法,我在网上看到很多文章都说的是go与cgo数据类型不同的问题~(我做了几个简单的小的demo,验证了确实是数据类型的问题… …)需要在go代码中先把数据类型进行转换,于是,我又开始研究官方文档了(此处省略一些很傻的坑…)看到官方文档给出了一些原始的C兼容数据类型(下图),我看见自己的go代码中传入的参数与返回值都是字符串类型,Python是利用ctypes来跟so模块进行交互,其中存在着一个代码的翻译过程,包括数据类型的翻译,如果需要传参获取接收返回值,需要在golang中将参数按照下表对应,定义成C语言的数据类型。
5. 我对自己最初的代码进行了如下调整:
- 对传入的参数进行了类型的转换
- 对返回值进行了类型转换:
注意:内部的数据类型不需要做任何改变,只需要更改传入的参数和返回值的类型即可!!我自己的方法中有很多数据类型,包括字节数组、字符串、一些切片等等。。我都转过,后来发现根本不用!!(还是我理解的不够深入…我悔过)
- 此时在python中,也不能简单的直接调用了,需要用对应的数据类型进行转换:
#!/user/bin/env python3
# -*- coding: utf-8 -*-
import ctypes
matchCommand = ctypes.CDLL("./matchCommand.so").matchCommand
# 显式声明参数和返回值的期望类型
matchCommand.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
matchCommand.restype = ctypes.c_char_p
# 这个地方在前面加b,是代表bytes
matchCommand(b"linux", b"yum remove")
至此,执行python文件之后,就成功了。整个过程我尽量进行了详细的回忆,如果有不准确的地方,欢迎指正(#^.^#)