为什么在Python3中可以使用ctypes修改不可变字节对象?
字节对象是。它不支持项目分配:为什么在Python3中可以使用ctypes修改不可变字节对象?,python,c,python-3.x,ctypes,Python,C,Python 3.x,Ctypes,字节对象是。它不支持项目分配: >>> bar = b"bar" >>> bar[0] = b"#" Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'bytes' object does not support item assignment c代码编译 gcc -shared -o clib.so -fPIC c
>>> bar = b"bar"
>>> bar[0] = b"#"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'bytes' object does not support item assignment
c代码编译
gcc -shared -o clib.so -fPIC clib.c
字节尝试
python代码
char* foo(char *bar) {
bar[0] = '#';
return bar;
}
import ctypes
clib = ctypes.CDLL('./clib.so')
bar = b"bar"
print("Before:", bar, id(bar))
clib.foo(bar)
print("After: ", bar, id(bar))
import ctypes
clib = ctypes.CDLL('./clib.so')
bar = "bar"
print("Before:", bar, id(bar))
clib.foo(bar)
print("After: ", bar, id(bar))
python代码输出
Before: b'bar' 140451244811328
After: b'#ar' 140451244811328
Before: bar 140385853714080
After: bar 140385853714080
str尝试
str对象在python3中也是不可变的,但与bytes对象不同,不能用ctypes修改它
python代码
char* foo(char *bar) {
bar[0] = '#';
return bar;
}
import ctypes
clib = ctypes.CDLL('./clib.so')
bar = b"bar"
print("Before:", bar, id(bar))
clib.foo(bar)
print("After: ", bar, id(bar))
import ctypes
clib = ctypes.CDLL('./clib.so')
bar = "bar"
print("Before:", bar, id(bar))
clib.foo(bar)
print("After: ", bar, id(bar))
python代码输出
Before: b'bar' 140451244811328
After: b'#ar' 140451244811328
Before: bar 140385853714080
After: bar 140385853714080
Python3中的
str
被抽象为Unicode,根据字符串中使用的最高Unicode字符,每个字符串可以存储为1、2或4字节。要将字符串传递给C函数,必须将其转换为特定的表示形式ctypes
在本例中,是将转换后的临时缓冲区传递给C,而不是原始缓冲区<代码>ctypes如果不正确地对函数进行原型化,或者将不可变对象发送给改变内容的函数,则会导致Python崩溃和损坏,在这种情况下,用户需要小心
在bytes
案例中ctypes
传递一个指向其内部字节缓冲区的指针,但不希望对其进行修改。考虑:
a = b'123'
b = b'123'
由于字节
是不可变的,因此Python可以自由地在a
和b
中存储相同的引用。如果将b
传递给ctypes
包装函数并对其进行修改,则该函数也可能损坏a
直截了当地说:
但是,您应该小心,不要将[不可变对象]传递给期望指向可变内存的指针的函数。如果您需要可变内存块,ctypes有一个create\u string\u buffer()
函数,它以各种方式创建这些块
Python3中的
str
被抽象为Unicode,根据字符串中使用的最高Unicode字符,每个字符串可以存储为1、2或4字节。要将字符串传递给C函数,必须将其转换为特定的表示形式ctypes
在本例中,是将转换后的临时缓冲区传递给C,而不是原始缓冲区<代码>ctypes如果不正确地对函数进行原型化,或者将不可变对象发送给改变内容的函数,则会导致Python崩溃和损坏,在这种情况下,用户需要小心
在bytes
案例中ctypes
传递一个指向其内部字节缓冲区的指针,但不希望对其进行修改。考虑:
a = b'123'
b = b'123'
由于字节
是不可变的,因此Python可以自由地在a
和b
中存储相同的引用。如果将b
传递给ctypes
包装函数并对其进行修改,则该函数也可能损坏a
直截了当地说:
但是,您应该小心,不要将[不可变对象]传递给期望指向可变内存的指针的函数。如果您需要可变内存块,ctypes有一个create\u string\u buffer()
函数,它以各种方式创建这些块
你是在幕后进行的,所以基本上任何事情都是可能的。好吧,我可以接受这一点,但为什么str对象不可能做同样的事情?你能展示你的字符串尝试的代码吗?它出现在“str trunt”标题下-我对我的问题做了一些修改,使它更容易阅读。你是在幕后进行的,所以基本上任何事情都是可能的。好吧,我可以接受这一点,但为什么str对象不可能做到同样的事情呢?你能展示你的字符串尝试的代码吗?它出现在“str true”标题下面-我对我的问题做了一些修改,使它更容易阅读。