字节对象是不可变的。它不支持项目分配:
>>> bar = b"bar"
>>> bar[0] = b"#"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'bytes' object does not support item assignmentstr对象也是不可变的:
>>> bar = "bar"
>>> bar[0] = "#"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment可以用ctype修改字节对象,而对str对象则不可能这样做。你能解释一下为什么吗?请看下面的例子。
c代码
char* foo(char *bar) {
bar[0] = '#';
return bar;
}c #代码编译
gcc -shared -o clib.so -fPIC clib.c字节尝试
python代码
import ctypes
clib = ctypes.CDLL('./clib.so')
bar = b"bar"
print("Before:", bar, id(bar))
clib.foo(bar)
print("After: ", bar, id(bar))python代码输出
Before: b'bar' 140451244811328
After: b'#ar' 140451244811328str企图
str对象在Python 3中也是不可变的,但是与字节对象不同,不可能用ctype修改它。
python代码
import ctypes
clib = ctypes.CDLL('./clib.so')
bar = "bar"
print("Before:", bar, id(bar))
clib.foo(bar)
print("After: ", bar, id(bar))python代码输出
Before: bar 140385853714080
After: bar 140385853714080发布于 2017-12-02 17:56:50
Python3中的str被抽象为Unicode,根据字符串中使用的最高Unicode字符,可以将每个字符串存储为1-、2-或4字节。若要将字符串传递给C函数,必须将其转换为特定的表示形式。在这种情况下,ctypes将转换后的临时缓冲区传递给C,而不是原始缓冲区。如果您的原型函数不正确,或者将不可变对象发送到更改内容的函数,ctypes可能会崩溃和损坏Python,在这些情况下,用户应该小心。
在bytes情况下,ctypes传递指向其字节内部缓冲区的指针,但并不期望对其进行修改。考虑:
a = b'123'
b = b'123'由于bytes是不可变的,所以Python可以在a和b中存储相同的引用。如果将b传递给ctypes-wrapped函数并对其进行修改,它也可能破坏a。
直接从ctypes文档
但是,您应该小心,不要将不可变对象传递给期望指向可变内存的指针的函数。如果您需要可变的内存块,ctype有一个
create_string_buffer()函数,它以各种方式创建这些块.
https://stackoverflow.com/questions/47609698
复制相似问题