Python2 & Python3 ctypes 字符串编码类型转换大坑

ctypes介绍

python标准库自带的模块,支持调用C的动态链接库文件(windows下为*.dll,linux下为*.so)
示例代码:

# 加载动态链接库文件
ll = cdll.LoadLibrary
lib = ll("lib/libTest.so")
# 生成函数指针
# 假设库中有函数int foo(char*)
foo = lib.foo
# 设置参数格式
foo.argtypes = [c_char_p]
# 设置返回值格式
foo.restype = c_int

事件的起源是,和学长一起做项目,学长留给我一个2700行的C++文件并表示”你要的接口我都已经写好了,你拿去直接用就行”。开心的我拿回去封装了就跑
其中有一个C++函数funcA,接受一个const char* rfile作为输入文件名,返回一个char* res作为结果。于是第一次就写了如下代码:

ll = cdll.LoadLibrary
lib = ll("lib/libTest.so")
funcA = lib.funcA
funcA.restype = c_char_p

res = funcA("test.dat")
arr = res.split(".")

在实验室用python2读了几个测试数据跑了一遍,没有问题
可是!!!回去以后在本机上用python3跑!!!res永远是None!!!

第一次尝试

在C++函数funcA中,cout<
惊讶的发现,输出结果是t…………
当时的第一反应是,只取到第一个字符,可能是在传参过程中,参数被解引用了。于是添加了一行funcA.argtypes = [c_char_p],说明传入参数是个指针
不出所料,没点卵用……

第二次尝试

网上找到类似案例,Converting python string object to c char* using ctypes-stackoverflow
根据高票答案指示,传参之前先对参数字符串进行编码:
res = funcA("test.dat".encode("utf-8"))
此时文件读取正常
可是下一行,对返回结果split的时候,又报错TypeError: a bytes-like object is required, not 'str'
联想起之前python2跑这段代码并没问题,python3和python2的一大区别就是字符串str默认采用unicode编码,这个问题就慢慢变得清晰了起来

结果

python3中,字符串str全部采用unicode编码。str提供一个encode(type) 函数,可以按照type指定的编码类型,将字符串转换为一个bytes 对象,即字节流
然而python2中,所谓的str ,其实是bytes !!!
更操蛋的是python2的str 居然还有一个encode() 方法……至今不明白他是想干什么……
所以问题就解决啦,归根结底是由于python3和python2中,字符串的默认编码不同导致的
最终代码:

ll = cdll.LoadLibrary
lib = ll("lib/libTest.so")
funcA = lib.funcA
funcA.argtypes = [c_char_p]
funcA.restype = c_char_p

res = funcA("test.dat".encode("utf-8")).decode()
arr = res.split(".")

你可能感兴趣的:(Python2 & Python3 ctypes 字符串编码类型转换大坑)