Home > Article > Backend Development > [Advanced] Python+Go - Let's find another way to improve computing performance
##/2 What is the reason for the return value error? /
In the last article, we seemed to have forgotten a picture.
The .go file belongs to Go. Without further ado, .so is the file used by Python to call Go. What is the .h file? ? ? It seems to have no sense of existence. Our problem lies in this .h file. Let’s open it and take a look
In fact, you can probably find out from the above that GoInt is actually GoInt64, and the type of GoInt64 is long long type. Is this a thing? ? ?
Actually, when we call the .so file in Python, we use the <span style="font-size: 18px;">ctypes</span>
module. This is There is a correspondence table.
##/3 Python, ctypes, c type Correspondence table/
Official website address:
https://docs.python.org/3.5/library/ctypes.html
ctypes type | C type | Python type |
c_bool | _Bool | bool (1) |
c_char | char | 1-character bytes object |
c_wchar | wchar_t | 1-character string |
c_byte | char | int |
c_ubyte | unsigned char | int |
c_short | short | int |
c_ushort | unsigned short | int |
c_int | int | int |
c_uint | unsigned int | int |
c_long | long | int |
c_ulong | unsigned long | int |
c_longlong | __int64 or long long | int |
c_ulonglong | unsigned __int64 or unsigned long long | int |
c_size_t | size_t | int |
c_ssize_t | ssize_t or Py_ssize_t | int |
c_float | float | float |
c_double | double | float |
c_longdouble | long double | float |
c_char_p | char * (NUL terminated) | bytes object or None |
c_wchar_p | wchar_t * (NUL terminated) | string or None |
c_void_p | void * | int or None |
根据上述表格我们可以发现,在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 < n; 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拿到的会是什么呢?拿到会和原来的一样,一堆数字,这里就不举栗子了。
/5 小结/
至此,基本上在Python调用Go代码上的大坑都解决了,最复杂的是返回字符串类型,查了很多相关资料才解决。
关于返回其他类型的Python的class怎么写,我相信已经难为不到你们了,最复杂的都解决了,最简单的还不会吗?(除字符串类型以外其他_fields_都是一个字段的)
我相信各位小伙伴学习能力还是很强的,人生苦短,Python当歌,加油,奥利给!
The above is the detailed content of [Advanced] Python+Go - Let's find another way to improve computing performance. For more information, please follow other related articles on the PHP Chinese website!