golang怎么执行python脚本并且带传入参数的 golang执行python代码 | 您所在的位置:网站首页 › golang执行python › golang怎么执行python脚本并且带传入参数的 golang执行python代码 |
1. 前言 在上一篇文章中,我们成功的通过 Python 调用 Go 代码,并且把计算密集的交给了 Go 来进行计算 虽然计算的很快,但是在获取返回值时,似乎有点让人诧异,并不是我们想象的那样子 2. 返回值错误原因? 在上一篇文章中,我们似乎都忘了一张图 .go 文件是 Go 的,不多说,.so 是 Python 调用 Go 的文件,那 .h 文件是什么? 似乎很没有存在感,我们的问题出,也就出在这个 .h 文件中,我们打开看一下 我们往下翻翻,会找到 extern 开头的声明,这个意思是将 Go 代码转为 C 代码一一对应的参数,可见,转为 C 的是 GoInt 类型,这个类型具体什么意思呢???再找找看 在上面其实大概可以发现,GoInt 其实就是 GoInt64,GoInt64 的类型是 long long 类型,这是玩意??? 其实我们在 Python 中调用 .so 文件使用的是 ctypes 模块,这个是有一个对应表的 3. 查看对应表 对应表可以参考官网地址: https://docs.python.org/3.5/library/ctypes.html 在 C 中的 long long 类型对应的 ctype 类型是 c_longlong 所以我们需要在 Python 将 .so 中的返回值改一下,不能使用系统默认的了。 代码如下: from ctypes import * import time class StructPointer(Structure): # 根据查表,C中的long long,对应的ctypes 是 c_longlong # _fields_必须是[](列表)类型,里面写对应的类型,固定格式 _fields_ = [("p", c_longlong,),] if __name__ == '__main__': beginTime = time.time() s = CDLL("s1.so") # 加载s1.so文件 s.run.restype = StructPointer # 声明.so的run函数返回值类型,固定格式 result = s.run(100000000) # 调用Go生成的.so文件里面的run函数 print("result:", result.p)# 此处需要调用.p来获取值,和 _fields_对应 endTime = time.time() print("耗时:", endTime - beginTime) 再次执行,结果如下: 可以看到,这次 Python 执行的结果和 Go 执行结果就一个样了。 继续,换个数字试试 基本可以确定,这次是没问题了 4. 如果是字符串,怎么办 Go 代码 package main import ( "C" //C必须导入 "fmt" ) //export run func run(n int) int{ /* 必须要export 函数名 //是注释的意思,相当于Python中的 # 我也是第一次见注释还有作用 */ sum := 0 for i := 0; i sum += i } fmt.Println("我是Go代码,我跑完了,我的结果是:",sum) return sum } //export speak func speak(n int) string{ return "OMG 996好累呀,难得休息一天,好好休息" } func main() { //main函数中什么都不要写,和包名main要对应 } 下面一起来理解 .h 文件。编译之后打开 .h 文件如下图所示: 可以看到,在 extern 的函数成了两个,但是他的返回值是 GoString,继续找 可以发现,其实 GoString 就是 _GoString_,继续找。 这次是一个结构体,里面其实是两个值,不在是单独的 long long 了,那 Python 中的继承类也要改一下了 下面基本同上 完整代码如下: from ctypes import * import time class StructPointer(Structure): # 根据查表,C中的long long,对应的ctypes 是 c_longlong # _fields_必须是[](列表)类型,里面写对应的类型,固定格式 _fields_ = [("p", c_longlong,),] class StrPointer(Structure): # typedef struct { const char *p; ptrdiff_t n; } _GoString_; # ptrdiff_t == long long _fields_ = [("p", c_char_p), ("n", c_longlong)] if __name__ == '__main__': beginTime = time.time() s = CDLL("s1.so") # 加载s1.so文件 s.run.restype = StructPointer # 声明.so的run函数返回值类型,固定格式 result = s.run(100000798) # 调用Go生成的.so文件里面的run函数 print("result:", result.p)# 此处需要调用.p来获取值,和 _fields_对应 s.speak.restype = StrPointer speakStr = s.speak() # 返回的是字节类型,需要转字符串,返回的内容在.p中,.n是切的长度,后面会跟一些介绍,不需要 speakStr = str(speakStr.p[:speakStr.n], encoding="utf-8") print("speak:",speakStr) endTime = time.time() print("耗时:", endTime - beginTime) 运行后的结果如下: 可以看到,调用 Go 代码成功的拿到了正确的字符串返回值 如果没有 .restype = StrPointer 拿到的会是什么呢? 拿到会和原来的一样,一堆数字,这里就不举例子了 |
CopyRight 2018-2019 实验室设备网 版权所有 |