【问题标题】:Cython function declarations when function steals a reference函数窃取引用时的 Cython 函数声明
【发布时间】:2017-01-29 20:18:17
【问题描述】:

有一些 Python C-API 函数会窃取一个传递参数的引用,例如 PyList_SetItem,而其他一些函数会增加参数的引用计数,例如 PyList_Append

我可以告诉 Cython 引用将被盗吗?还是我需要手动使用Py_INCREF

from cpython.object cimport PyObject
from cpython.ref cimport Py_INCREF

cdef extern from "Python.h":
    void PyList_SetItem(object list, Py_ssize_t i, object o)

cpdef void func(list lst, object item):
    Py_INCREF(item)
    PyList_SetItem(lst, 0, item)

我知道如果一个函数返回一个借用的引用,则可以更改返回类型(PyObject * 用于借用的引用,object 用于未借用的引用):

from cpython.object cimport PyObject
from cpython.ref cimport Py_INCREF

cdef extern from "Python.h":
    PyObject* PyList_GetItem(object list, Py_ssize_t index)
    object PyObject_GetItem(object o, object key)

但这似乎不适用于被盗的参考文献(或者我的想法是错误的?):

from cpython.object cimport PyObject

cdef extern from "Python.h":
    void PyList_SetItem(object list, Py_ssize_t i, PyObject *o)

cpdef void func(list lst, object item):
    PyList_SetItem(lst, 0, <PyObject*>item)

【问题讨论】:

标签: python cython python-c-api


【解决方案1】:

在 Cython (yet?) 中没有自动处理“窃取”的方法,因此必须退回到有些尴尬的手动处理(正如问题本身所指出的那样):

%%cython
from cpython.ref cimport Py_INCREF
from cpython.list cimport PyList_SetItem

def replace(list lst, object item):
    Py_INCREF(item) # prepare for stealing 
    PyList_SetItem(lst, 0, item)

行为符合预期:

import sys
a, b= float(), float()
lst = [a]
print(sys.getrefcount(a), sys.getrefcount(b))
# refcount(a)=3 and refcount(b)=2
replace(lst, b)
print(sys.getrefcount(a), sys.getrefcount(b))
# refcount(a)=3 and refcount(b)=2

【讨论】:

  • 这个答案是使这个问答成为可能的重复目标的一个步骤。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-01
  • 2012-05-02
  • 2013-09-27
  • 1970-01-01
  • 1970-01-01
  • 2010-12-20
  • 1970-01-01
相关资源
最近更新 更多