【问题标题】:Is PyBuffer_Release required after Py_BuildValue("y#", ...)?Py_BuildValue("y#", ...) 之后是否需要 PyBuffer_Release?
【发布时间】:2018-07-04 11:25:48
【问题描述】:

如果它有所作为,我对 Python 3 的答案很感兴趣。

文档状态(herehere)应在 PyArg_Parse*() 之后使用 s*y* 调用 PyBuffer_Release()

没有任何关于Py_BuildValue() 的文章。是疏忽还是Py_BuildValue() simple Py_DECREF() 就足够了?

这是我的具体情况:

uint8_t buf = (uint8_t *)malloc(bufSize);
PyObject *pyBuf = Py_BuildValue("y#", (char *)buf, bufSize);
free(buf);

// do something with pyBuf

// maybe a PyBuffer_Release(get_underlying_buffer(pyBuf)) here?
Py_DECREF(pyBuf);

【问题讨论】:

    标签: python python-c-api pybuffer


    【解决方案1】:

    我认为没有:

    1. PyArg_Parse*Py_BuildValue 函数中,y# 指的是字符串和长度,而不是缓冲区,因此没有要释放的底层缓冲区对象。

    2. Py_BuildValue 的文档说:

      当内存缓冲区作为参数传递以提供数据以构建对象时,对于 s 和 s# 格式,需要的数据被复制。调用者提供的缓冲区永远不会被 Py_BuildValue() 创建的对象引用。

      锁定PyArg_Parse* 使用的缓冲区的目的是,您已经引用到 Python 到 C 的一些数据 out,并且您想要在 C 中处理它,而不会被 Python 修改。在这种情况下,您已将一些数据从 C 中复制到 Python,因此无需保护原始数据不被修改。

    【讨论】:

    • “在这种情况下,您已将一些数据从 C 复制到 Python,因此无需保护原始数据不被修改。” - 我认为此时 Python 可能确定有一个新对象引用了该复制的缓冲区,因此在Py_buffer 的构造过程中增加了一些内部引用计数器,稍后必须由PyBuffer_Release() 释放。至少,这是我害怕的。也许新创建的对象本身就是Py_buffer。也许稍后我会创建一些测试代码来确定创建了哪些对象以及它们拥有哪些资源。
    • 当我对此进行测试时,新创建的对象是 bytes 对象(唯一的其他现实选项是 bytearray)。这确实暴露了缓冲区接口,因此可以获得Py_buffer。然而,即使Py_BuildValue 生成了一个需要释放缓冲区的内容,您也无能为力,因为您无权访问它创建的任何Py_buffer
    • 所以基本上,无论bytes 中自动持有的资源,这些资源都应该由bytes 对象自动释放。这就说得通了。我认为绝对可以肯定的是,必须查找 python 代码。现在对我来说已经足够了。
    猜你喜欢
    • 2014-11-28
    • 1970-01-01
    • 2011-04-09
    • 2011-10-28
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    • 2019-10-13
    • 2014-11-21
    相关资源
    最近更新 更多