返回numpy数组别名内部数组时如何处理引用计数?

2024-09-29 21:39:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个名为ctcorrgen的类,它正在进行一些数字处理,并通过指向内部数组的常量指针一次返回一行结果。我想将这个内部数组包装成一个只读Numpy数组并返回它,如下所示:

static inline PyObject* ctcorrgen_yield_row(object &object) {
    // extract corrgen base
    ctcorrgen &corrgen = extract<ctcorrgen&>(object);

    // get row of data
    const cfloat* row = corrgen.yield_row();
    if (row == nullptr) {
        return detail::none();        
    } else {
        // build read-only array around data
        npy_intp len = corrgen.framesize();
        return PyArray_New(
            &PyArray_Type, 1, &len, NPY_COMPLEX64, NULL, (void*)row, 0,
            NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ALIGNED, NULL
        );
    }
}

我的问题是,如何设置新的array对象引用它所创建的对象,以便在处理完数组之前它不会被垃圾收集(从而破坏底层缓冲区)?我使用的是boost::python,但我怀疑这需要比我更直接地了解pythonc-API。你知道吗


Tags: datalenreturnobjectextract数组arraynull
1条回答
网友
1楼 · 发布于 2024-09-29 21:39:22

好吧,我想我找到了答案,对任何在我之后的人来说。你知道吗

查看PyArrayObject的定义:

typedef struct PyArrayObject {
    PyObject_HEAD
    char *data;
    int nd;
    npy_intp *dimensions;
    npy_intp *strides;
    PyObject *base;
    PyArray_Descr *descr;
    int flags;
    PyObject *weakreflist;
} PyArrayObject;

关键是base pointer

PyObject *PyArrayObject.base

This member is used to hold a pointer to another Python object that is related to this array. There are two use cases: 1) If this array does not own its own memory, then base points to the Python object that owns it (perhaps another array object), 2) If this array has the (deprecated) NPY_ARRAY_UPDATEIFCOPY or :c:data:NPY_ARRAY_WRITEBACKIFCOPY`: flag set, then this array is a working copy of a “misbehaved” array. When PyArray_ResolveWritebackIfCopy is called, the array pointed to by base will be updated with the contents of this array.

结合pyu New的这一段:

Warning

If data is passed to PyArray_NewFromDescr or PyArray_New, this memory must not be deallocated until the new array is deleted. If this data came from another Python object, this can be accomplished using Py_INCREF on that object and setting the base member of the new array to point to that object. If strides are passed in they must be consistent with the dimensions, the itemsize, and the data of the array.

因此,我认为这样的方法是建立所需关系的合适方法(对于Numpy>;=1.7)

// increment reference to ctcorrgen object and set base pointer
// of array, this will establish an ownership link so that
// ctcorrgen won't be destroyed before the array.
incref(object.ptr());
PyArray_SetBaseObject((PyArrayObject*)array, object.ptr());

相关问题 更多 >

    热门问题