如何清除包含对象的PyList对象?

时间:2018-08-20 18:19:29

标签: python ctypes python-c-api

我正在尝试清除使用ctypes传递给C函数的Python列表。我在this链接上找到的调用有时似乎可以正常工作,但是当我传递的列表包含其他列表或类作为元素时,我会遇到段错误。

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

export class TableComponent implements OnInit {
  private rowData: any;
  private columnDefs;

  constructor(
    private service: Service,
    private http: HttpClient,
    vcr: ViewContainerRef,
    public dialog: MatDialog, 
    private fb: FormBuilder
  ) {
    this.columnDefs = [{
        headerName: 'id',
        field: 'id',
        hide: true
      },
      {
        headerName: 'First Name',
        field: 'firstName'
      }
    ];
  }

  ngOnInit() {
    this.service.employees.subscribe(employees => this.rowData = employees);
    this.service.getData();
  }

}

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

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)

下面是一个示例,它可以正确处理各种原始数据类型。

#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;
}

以下是段错误的示例:

>>> 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()

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

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;
} 

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

1 个答案:

答案 0 :(得分:2)

我不知道这是否是段错误的直接原因,但是您不能从作为CDLL加载的库中使用Python API。您必须使用PyDLL。使用CDLL,Python会先释放GIL,然后再从该库中调用函数,而您需要GIL。