You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 04:23:14