如何清除包含对象的PyList对象? [英] How to clear a PyList object that contains objects?

查看:84
本文介绍了如何清除包含对象的PyList对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图清除使用ctypes传递给C函数的Python列表.我在链接中找到的呼叫有时可以正常工作,但是当我通过列表时包含其他列表或类作为元素,我会遇到段错误.

I am trying to clear a Python list I pass to a C function using ctypes. The calls I found at this link seem to work sometimes, but when the list I pass in contains other lists or classes as elements I get a segfault.

我有一个看起来像这样的文件foo.py:

I have a file foo.py that looks like this:

import ctypes
_libpractice=ctypes.CDLL('./_practice.so', mode=ctypes.RTLD_GLOBAL)

_libpractice.update.argtypes = [ctypes.py_object]
_libpractice.update.restype = ctypes.py_object

def c_update(my_list):
    return _libpractice.update(my_list)

和一个如下所示的文件Practice.c:

and a file practice.c that looks like this:

#include <Python.h>
#include <stdio.h>

PyObject* update(PyObject* list){
    Py_INCREF(list);
    Py_ssize_t len = PySequence_Length(list);    
    PySequence_DelSlice(list, 0, len);

    return list;
}

这里是一个示例,它可以正确处理各种原始数据类型.

Here is an example of it working correctly with various primitive data types.

>>> import foo
>>> a = [1,2,3,4,5.5,'a',6]
>>> foo.c_update(a)
[]
>>>

以下是段错误的示例:

>>> b = [1,2,3,[],5]
>>> foo.c_update(b)
Segmentation fault (core dumped)

我想出了一种解决方法,方法是对列表中的每个项目调用PySequence_GetItem(),然后像这样调用PySequence_DelSlice():

I have figured out a way around this by calling PySequence_GetItem() on every item in the list and then calling PySequence_DelSlice() like so:

PyObject* update(PyObject* list){
    Py_INCREF(list);
    Py_ssize_t len = PySequence_Length(list);

    for(Py_ssize_t i = 0; i<len; i++){
        PyObject* item = PySequence_GetItem(list,i);
    }

    PySequence_DelSlice(list, 0, len);    

    return list;
} 

但是,如果我将一个类作为列表的元素传递,则从列表中删除析构函数后将不会调用该析构函数.

However, if I pass a class as an element of the list, the destructor is not called after it is deleted from the list.

>>> import foo
>>> class Sample:
...     def __del__(self):
...         print('del called')
...
>>> a = Sample()
>>> a = 3
del called
>>> b = Sample()
>>> my_list = [1,b,3,[]]
>>> foo.c_update(my_list)
[]
>>>

如何清除同时传递的列表,同时确保我正确地处理了引用计数?

How can I clear the list I am passing in while at the same time making sure I am correctly handling reference counts?

推荐答案

我不知道这是否是段错误的直接原因,但是您不能在以CDLL加载的库中使用Python API.您必须使用PyDLL.使用CDLL,Python会在从该库调用函数之前释放GIL,而您需要GIL.

I don't know if this is the direct cause of the segfault, but you cannot use the Python API from within a library loaded as CDLL. You have to use PyDLL. With CDLL, Python will release the GIL before calling functions from that library, and you need the GIL.

这篇关于如何清除包含对象的PyList对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆