Python 3.6.5 ctypes文档Surprises部分是否过时?实测结果不符
关于ctypes中
c_char_p.value is c_char_p.value返回值的疑问解答 你碰到的这个差异,核心原因是你最初的代码没有正确实例化c_char_p对象,而是直接操作了类本身,这和文档里描述的场景完全不匹配。
问题出在哪?
你写的s = c_char_p是把c_char_p这个类本身赋值给了变量s,而不是创建一个类的实例。当你给s.value(本质是c_char_p.value这个类属性)赋值时,它就变成了一个普通的Python类属性——每次访问这个属性,返回的都是同一个字符串对象,所以用is判断自然会得到True。
而Python 3.6.5版的ctypes手册Surprises章节里描述的,是实例对象的value属性行为:当你创建c_char_p的实例(也就是加上括号s = c_char_p())时,value是一个动态属性——每次访问它,ctypes都会从底层的C内存中读取数据,然后新建一个Python字符串对象返回。两次访问得到的是不同的对象,所以s.value is s.value就会返回False,这正是文档里提到的"惊喜"(或者说坑点)。
修正后的验证代码
你自己发现了括号的问题,这里再明确正确的写法和结果:
针对c_char_p(字节字符串,对应C的char*)
from ctypes import * s = c_char_p() # 必须创建实例,不能直接用类 s.value = b'abc def ghi' # 赋值必须是字节串(带b前缀) print(s.value is s.value) # 运行后输出:False
针对c_wchar_p(Unicode字符串,对应C的wchar_t*)
如果你用宽字符版本,逻辑是一样的,只是赋值用普通Unicode字符串:
from ctypes import * s = c_wchar_p() s.value = 'abc def ghi' print(s.value is s.value) # 同样输出:False
额外注意点
- 一定要区分类属性和实例属性:操作类的
value不会触发ctypes的特殊逻辑,只有实例的value才会有每次访问重建对象的行为。 - 严格匹配字符串类型:
c_char_p对应C的字节指针,必须用字节串赋值;c_wchar_p对应宽字符指针,用普通Unicode字符串,混用会引发错误或者不符合预期的行为。
内容的提问来源于stack exchange,提问作者user9611000
相关产品推荐
相关产品推荐

