python - 为什么可以在 python 3 中使用 ctypes 修改不可变字节对象?

标签 python c python-3.x ctypes

字节对象是immutable .它不支持项目分配:

>>> 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

str 对象也是不可变的:

>>> bar = "bar"
>>> bar[0] = "#"
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

可以用 ctypes 修改 bytes 对象,而不能用 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' 140451244811328

str 尝试

str 对象在 Python 3 中也是不可变的,但与 bytes 对象不同,它不能用 ctypes 修改它。

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

最佳答案

Python 3 中的

str 被抽象为 Unicode,并且可以存储为每个字符串 1、2 或 4 字节,具体取决于字符串中使用的最高 Unicode 字符。要将字符串传递给 C 函数,必须将其转换为特定的表示形式。 ctypes 在这种情况下将转换后的临时缓冲区传递给 C 而不是原始缓冲区。 ctypes 可能会崩溃并损坏 Python,如果您对函数进行原型(prototype)设计不正确或将不可变对象(immutable对象)发送到会改变内容的函数,在这些情况下用户需要小心。

bytes 的情况下,ctypes 传递一个指向其内部字节缓冲区的指针,但不希望它被修改。考虑:

a = b'123'
b = b'123'

由于 bytes 是不可变的,Python 可以自由地在 ab 中存储相同的引用。如果您将 b 传递给一个 ctypes 包装的函数并且它对其进行了修改,它也可能会损坏 a

直接来自 ctypes documentation :

You should be careful, however, not to pass [immutable objects] to functions expecting pointers to mutable memory. If you need mutable memory blocks, ctypes has a create_string_buffer() function which creates these in various ways....

关于python - 为什么可以在 python 3 中使用 ctypes 修改不可变字节对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47609698/

相关文章:

python - 如何分离xpath语句的输出

python - NLTK:设置代理服务器

c - 在递归函数中打印函数参数

python - 使用 grequests 发布 json 数据?

python - 如何在Python中执行静态程序分析以查找具有某些属性的函数?

python - 为什么 error_messages 在元类中不起作用?

c - 检索独立 MATLAB 程序的路径和文件名

c - 编写我自己的 shell,未声明的标识符 "output"

python - 你可以使用 python 套接字进行 docker 容器通信吗?

带有用户输入的 Python 3 单元测试