gpt4 book ai didi

python - 如何将 PyObject* 指针设置为 None?

转载 作者:行者123 更新时间:2023-11-28 18:39:11 27 4
gpt4 key购买 nike

我想用一个指针来改变一个python对象的值,这是我试过的:

这个有效:

def main():
cdef int i
cdef int* iptr
i = 5
iptr = &i
iptr[0] = 1
print(i) # this works, prints 1

还有这个:

cdef class A:
cdef int i
def __init__(self, i): self.i = i

def main():
cdef int* ptr
cdef A a

a = A(5)
ptr = &a.i
ptr[0] = 1
print(a.i) # this works too

但是当我尝试对对象使用类似的代码时,我无法让它工作:

from cpython cimport PyObject

cdef class A:
cdef object o
def __init__(self, o): self.o = o

def main():
cdef PyObject* ptr
cdef A a

a = A(list())
# I also tried with `<void*>a.o`, `<PyObject*>a` and `<void*>a`
ptr = <PyObject*>a.o

# this segfaults
# ptr[0] = dict()
# print(a.o)

# this doesnt compile: Cannot convert Python object to 'PyObject'
# ptr[0] = None
# print(a.o)

# this doesnt compile: incompatible types when assigning to type ‘PyObject’ from type ‘struct PyObject *’
# ptr[0] = <PyObject>None
# print(a.o)

# this doesnt compile: Cannot assign type 'PyObject *' to 'PyObject'
# ptr[0] = <PyObject*>None
# print(a.o)

最佳答案

如果您愿意将要更改的对象引用声明为 PyObject *,而不是 object,则可以这样做。此外,为了使其工作,您必须自己管理对象的引用计数。这就是你在做的交易——一旦你放弃了获取和设置变量的 Python 方式,你就进入了 C 风格的内存管理领域,一个错误可能会导致你泄漏内存、访问无效数据、删除你的对象在你完成它们之前,并且在你犯下内存管理罪之后很久就会出现神秘的错误。因此,我真的建议不要走这条路,而是使用标准的 pythonic 方式设置变量来引用对象。

但是,如果您确实需要,此代码可以按照您希望示例运行的方式运行。

from cpython cimport PyObject
from cpython.ref cimport Py_INCREF, Py_XDECREF


cdef class A:
cdef PyObject *o

def __init__(self, o):
cdef PyObject *tmp

tmp = self.o
Py_INCREF(o)
self.o = <PyObject *>o
Py_XDECREF(tmp)


def main():
cdef PyObject **ptr
cdef PyObject *tmp
cdef A a

a = A(list())
ptr = &a.o

new_obj = dict()

tmp = ptr[0]
Py_INCREF(new_obj)
ptr[0] = <PyObject *>new_obj
Py_XDECREF(tmp)

print <object>a.o

请注意,每当我们更改 PyObject 引用时,我们首先递增新对象的引用,更改指针,然后递减对旧对象的引用。我建议您始终遵循该模式 - 在递增之前递减会导致错误,如果您重置变量以引用同一对象,您可能会释放仍在使用的对象。

此外,请务必在操作 Python 对象(包括更新其引用计数)时保持 GIL。

似乎没有办法说服 Cython 为您提供指向对象引用的指针,除非您以 C 风格声明对象引用。 (即 PyObject * 而不是 object ——尽管当你的程序运行时这两件事实际上是一样的。区别只在编译时,Cython 会自动执行object 变量而非 PyObject * 变量的引用管理。)

关于python - 如何将 PyObject* 指针设置为 None?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28801871/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com