Python 3.11下使用ctypes实现memset的两个技术疑问
关于Python中实现memset置零bytes缓冲区的疑问解答
问题1:是否必须自行定义Py_buffer类,是否有预定义的版本?
ctypes库中并没有预定义Py_buffer结构体,因此你确实需要自行定义。你的定义是正确的,字段的顺序、类型完全匹配CPython官方的Py_buffer结构定义,能保证和Python C API的交互正常。
问题2:我对PyBuffer_Release()的使用是否正确?
你的使用方式是完全正确的。根据Python缓冲区API的要求,调用PyObject_GetBuffer()获取缓冲区后,必须调用PyBuffer_Release()来释放相关资源。你将释放操作放在finally块中,确保无论try块内的memset操作是否成功,都会执行资源释放,避免了潜在的资源泄漏问题。
你的实现代码
def memset(bytes_object): import ctypes # Define the Py_buffer structure class Py_buffer(ctypes.Structure): _fields_ = [ ('buf', ctypes.c_void_p), ('obj', ctypes.py_object), ('len', ctypes.c_ssize_t), ('itemsize', ctypes.c_ssize_t), ('readonly', ctypes.c_int), ('ndim', ctypes.c_int), ('format', ctypes.c_char_p), ('shape', ctypes.POINTER(ctypes.c_ssize_t)), ('strides', ctypes.POINTER(ctypes.c_ssize_t)), ('suboffsets', ctypes.POINTER(ctypes.c_ssize_t)), ('internal', ctypes.c_void_p), ] buf = Py_buffer() ctypes.pythonapi.PyObject_GetBuffer(ctypes.py_object(bytes_object), ctypes.byref(buf), ctypes.c_int(0)) try: ctypes.memset(buf.buf, 0, buf.len) finally: ctypes.pythonapi.PyBuffer_Release(ctypes.byref(buf)) obj = bytes("hello world", "ascii") print("before:", repr(obj)) memset(obj) print("after:", repr(obj))
代码运行输出
before: b'hello world' after: b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
旧版实现(使用已废弃的PyObject_AsCharBuffer)
def memset_old(bytes_object: bytes): import ctypes if not isinstance(bytes_object, bytes): raise TypeError(f"expected bytes, not {type(bytes_object)}") data = ctypes.POINTER(ctypes.c_char)() size = ctypes.c_int() ctypes.pythonapi.PyObject_AsCharBuffer(ctypes.py_object(bytes_object), ctypes.pointer(data), ctypes.pointer(size)) ctypes.memset(data, 0, size.value) obj = bytes("hello world", "ascii") print("old before:", repr(obj)) memset_old(obj) print("old after:", repr(obj))
内容的提问来源于stack exchange,提问作者johanrex
相关产品推荐
相关产品推荐

