PyArg_ParseTuple SegFaults в CApi

#python #numpy #python-c-api

#python #numpy #python-c-api

Вопрос:

Я пишу код, пытаясь привыкнуть к C API массивов NumPy.

 #include <Python.h>
#include "numpy/arrayobject.h"
#include <stdio.h>
#include <stdbool.h>


static char doc[] =
"Document";

static PyArrayObject *
    trace(PyObject *self, PyObject *args){

    PyArrayObject *matin;

    if (!PyArg_ParseTuple(args, "O!",amp;PyArray_Type, amp;matin))
         return NULL;

    printf("a");
    return matin;
}

static PyMethodDef TraceMethods[] = {
    {"trace", trace, METH_VARARGS, doc},
    {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC
inittrace(void)
{
    (void) Py_InitModule("trace", TraceMethods);
    import_array();
}
  

Это урезанная версия. Я просто хочу иметь возможность получить объект типа PyArrayObject и вернуть его обратно. К сожалению, это также приводит к SegFault.

Linux, 64-разрядная версия, Python 2.7.1

Ответ №1:

Из документации:

O (object) [PyObject *]
Хранит объект Python (без какого-либо преобразования) в указателе объекта C. Таким образом, программа C получает фактический объект, который был передан. Количество ссылок на объект не увеличивается.Сохраненный указатель не равен нулю.

O! (object) [typeobject, PyObject *]
Хранит объект Python в указателе объекта C. Это похоже на O , но…

Вы возвращаете украденную ссылку. Сначала увеличьте его.

Комментарии:

1. Я не знаком с архитектурой программного обеспечения на C, но я предполагаю, что когда я не увеличиваю ссылку, PYINCREF(the_python_object); тогда сборщик мусора определяет, что его ссылка равна 0, и освобождает эту память. (поправьте меня, если я ошибаюсь)

2. По сути, да, но это refcount, уменьшающийся до 0, который вызывает GC, а не наоборот.