Расширение объекта Python, которое получает список в конструкторе, никогда не проходит этап создания (SIGSEV), почему?

Я много времени борюсь с ошибкой, и у меня не хватает идей о том, что происходит и почему это не работает.

Прежде всего, я пытаюсь создать новый тип объекта для Python с помощью расширения C. Этот объект создается с использованием списка, массива numpy и т. Д. Но я даже не могу заставить эту часть работать.

Фактический минимальный код, который терпит неудачу:

    #include <python2.7/Python.h>
    #include <python2.7/structmember.h>
    #include <numpy/arrayobject.h>
    #include "../python/NumpyHelperFuncs.h"
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    using namespace std;

    typedef struct {
        PyObject_HEAD
    } CondensedMatrix;

    static void condensedMatrix_dealloc(CondensedMatrix* self){
        self->ob_type->tp_free((PyObject*)self);
    }

    static PyObject* condensedMatrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds){
        CondensedMatrix *self;
        self = (CondensedMatrix*) type->tp_alloc(type, 0);
        return (PyObject *) self;
    }

    static int condensedMatrix_init(CondensedMatrix *self, PyObject *args, PyObject *kwds){
        PyObject* input;
        PyArrayObject* rmsd_numpy_array;
        cout<<"Minimum class creation"<<flush<<endl;

        if (! PyArg_ParseTuple(args, "O",&input)){
            PyErr_SetString(PyExc_RuntimeError, "Error parsing parameters.");
            return -1;
        }
        rmsd_numpy_array = (PyArrayObject *) PyArray_ContiguousFromObject(input, PyArray_FLOAT, 1, 1);
        Py_DECREF(rmsd_numpy_array);
        return 0;
    }

    static PyMemberDef condensedMatrix_members[] = {
        {NULL}  /* Sentinel */
    };


    static PyMethodDef condensedMatrix_methods[] = {
        {NULL}  /* Sentinel */
    };

    static PyTypeObject CondensedMatrixType = {
        PyObject_HEAD_INIT(NULL)
        0,                                              /*ob_size*/
        "condensedMatrix.CondensedMatrixType",          /*tp_name*/
        sizeof(CondensedMatrix),    /*tp_basicsize*/
        0,                         /*tp_itemsize*/
        (destructor)condensedMatrix_dealloc, /*tp_dealloc*/
        0,                         /*tp_print*/
        0,                         /*tp_getattr*/
        0,                         /*tp_setattr*/
        0,                         /*tp_compare*/
        0,                         /*tp_repr*/
        0,                         /*tp_as_number*/
        0,                         /*tp_as_sequence*/
        0,                         /*tp_as_mapping*/
        0,                         /*tp_hash */
        0,                         /*tp_call*/
        0,                         /*tp_str*/
        0,                         /*tp_getattro*/
        0,                         /*tp_setattro*/
        0,                         /*tp_as_buffer*/
        Py_TPFLAGS_DEFAULT| Py_TPFLAGS_BASETYPE ,                       /*tp_flags*/
        "Condensed matrix as in pdist",         /* tp_doc */
        0,                     /* tp_traverse */
        0,                     /* tp_clear */
        0,                     /* tp_richcompare */
        0,                     /* tp_weaklistoffset */
        0,                         /* tp_iter */
        0,                         /* tp_iternext */
        condensedMatrix_methods,   /* tp_methods */
        condensedMatrix_members,   /* tp_members */
        0,                         /* tp_getset */
        0,                         /* tp_base */
        0,                         /* tp_dict */
        0,                         /* tp_descr_get */
        0,                         /* tp_descr_set */
        0,                         /* tp_dictoffset */
        (initproc)condensedMatrix_init, /* tp_init */
        0,                              /* tp_alloc */
        condensedMatrix_new,                /* tp_new */
    };

    #ifndef PyMODINIT_FUNC  /* declarations for DLL import/export */
    #define PyMODINIT_FUNC void
    #endif

    PyMODINIT_FUNC initcondensedMatrix(void){
        PyObject* module;

        if (PyType_Ready(&CondensedMatrixType) < 0)
            return;

        module = Py_InitModule3("condensedMatrix", NULL,"Fast Access Condensed Matrix");
        if (module == NULL)
              return;

        Py_INCREF(&CondensedMatrixType);
        PyModule_AddObject(module, "CondensedMatrix", (PyObject*) &CondensedMatrixType);
    }

Этот код был написан в соответствии с советами (и копированием / вставкой): http://docs.python.org/exnding/newtypes.html#id2

Я протестировал код Noddy, и он работает, но если я добавлю четвертый параметр для получения списка, он также завершится с sigsev.

Я компилирую приведенный выше код с помощью:

gcc -pthread -fno-strict-aliasing -fmessage-length=0 -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables -fasynchronous-unwind-tables  -fPIC  -c matrix.cpp

g++ -pthread -shared matrix/matrix.o -lpython2.7 -o condensedMatrix.so -fopenmp

И я использую его с: if name == 'main': data_con = [3,4,5,6] matrix = CondensedMatrix (data_con)

Я также читал PyArg_ParseTuple SegFaults в CApi

Кто-нибудь знает, почему он делает segfault после pyarg_parsetuple?

Ubuntu 12.04, gcc 4.6.3, Python 2.7.3

Спасибо!


person Dows    schedule 08.08.2012    source источник
comment
Подключить к нему отладчик и пройти через него?   -  person favoretti    schedule 08.08.2012


Ответы (1)


Итак, похоже, что ошибку действительно было очень легко решить, так как единственное, что нужно было, - это отсутствующий 'import_array ();' предложение в функции init:

PyMODINIT_FUNC initcondensedMatrix(void){
    PyObject* module;

    if (PyType_Ready(&CondensedMatrixType) < 0)
        return;

    module = Py_InitModule3("condensedMatrix", NULL,"Fast Access Condensed Matrix");
    if (module == NULL)
          return;

    Py_INCREF(&CondensedMatrixType);
    PyModule_AddObject(module, "CondensedMatrix", (PyObject*) &CondensedMatrixType);
    import_array();
}

И это все ...

person Dows    schedule 15.08.2012