Golang生成Python动态链接库(python调用Go代码)

Golang生成Python动态链接库(python调用Go代码)

    • 前言
    • 使用环境介绍
    • 处理过程

前言

我们可以使用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

处理过程

  1. 在自己需要导出的函数上方加上// export 函数名,注意这行注释一定要加上(此外要注意要有main函数,不管main函数上是否有内容,此处我的main函数是空的~想直接在python中写调用)。
    如图所示:
    Golang生成Python动态链接库(python调用Go代码)_第1张图片

  2. 除了自己的程序需要的包以外,还需要导入import "C"包,因为在调用过程中需要用C来做一个媒介。如图所示:
    Golang生成Python动态链接库(python调用Go代码)_第2张图片

  3. 如果是Windows系统,需要安装MingW64----windows版本的c/c++编译器(如果已经安装了可以跳过此步骤,不确定是否安装的话可以使用gcc -v在命令行中查看是否安装成功)。
    下载链接(离线版):https://sourceforge.net/projects/mingw-w64/files/latest/download,
    官网地址为
    :https://sourceforge.net/projects/mingw-w64/files/mingw-w64/
    还可以点击我的网盘链接下载:https://pan.baidu.com/s/19zOjXVtmpSZffdZAQm9xLQ,提取码:5bnl
    可能由于我自身对MingW64的了解不太多,这个MingW64我在官网下载的时候,自己配置时总是不太全,有同样困扰的小伙伴可以直接下载我网盘提供的安装包下载安装好,按我的步骤做就可以直接用了,我下载的是离线的(注意我的我网盘里的安装包仅适用于windows64位),解压后放到一个合适的位置,接下来就是设置环境变量:右击“我的电脑”—“属性”—“高级系统设置”—“环境变量”—选中“Path”—“系统变量”下的“编辑”:
    Golang生成Python动态链接库(python调用Go代码)_第3张图片
    接着点击“新建”:将bin目录路径放进去,我的路径在:D:\MinGW\mingw64\bin
    Golang生成Python动态链接库(python调用Go代码)_第4张图片
    在cmd中输入gcc -v,有返回的版本结果信息等即可。
    Golang生成Python动态链接库(python调用Go代码)_第5张图片

  4. 然后回到刚才的地方,由于此处我用的是Windows,将go文件编译成dll即可,如果是Linux就编译成so(但事实上我用的windows转换成.so文件也依旧可以使用hiahia~)。语法格式为(在Terminal输入即可):

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语言的数据类型。
Golang生成Python动态链接库(python调用Go代码)_第6张图片
5. 我对自己最初的代码进行了如下调整:

  • 对传入的参数进行了类型的转换
    Golang生成Python动态链接库(python调用Go代码)_第7张图片
  • 对返回值进行了类型转换:
    在这里插入图片描述
    注意:内部的数据类型不需要做任何改变,只需要更改传入的参数和返回值的类型即可!!我自己的方法中有很多数据类型,包括字节数组、字符串、一些切片等等。。我都转过,后来发现根本不用!!(还是我理解的不够深入…我悔过)
  1. 此时在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文件之后,就成功了。整个过程我尽量进行了详细的回忆,如果有不准确的地方,欢迎指正(#^.^#)

你可能感兴趣的:(go,python,golang,python,golang,go)