Python 我的PyCFunction第一次工作,但在连续迭代后会导致segfault
我想用c编写一个python对象,其中包含一个numpy向量(实际上有两个,但在这个最小的示例中只有一个) 首先,我只想创建一个具有numpy数组的对象,并查看是否可以将其添加到循环中的所有数组元素中。但即使这样,也会导致奇怪的(可复制的)行为和错误 以下是发生的情况(回复): 我可以这样解决这个问题:Python 我的PyCFunction第一次工作,但在连续迭代后会导致segfault,python,numpy,python-extensions,Python,Numpy,Python Extensions,我想用c编写一个python对象,其中包含一个numpy向量(实际上有两个,但在这个最小的示例中只有一个) 首先,我只想创建一个具有numpy数组的对象,并查看是否可以将其添加到循环中的所有数组元素中。但即使这样,也会导致奇怪的(可复制的)行为和错误 以下是发生的情况(回复): 我可以这样解决这个问题: ... r2 = r.add() >>> r3 = r2.add() >>> r4 = r3.add() >>> r4.runs array
... r2 = r.add()
>>> r3 = r2.add()
>>> r4 = r3.add()
>>> r4.runs
array([ 4., 5., 6., 7., 8., 9., 10., 11., 12.])
我怀疑这与参考计数有关?我是一个完全的新手,对此一无所知。谢谢你的帮助。此功能(或我对它的使用)很可能是罪犯:
static PyObject * Rle_add(Rle* self)
{
int N = (int)PyArray_DIM(self->runs, 0);
double *x = (double*)PyArray_DATA(self->runs);
add(x, N);
return (PyObject *)self;
}
它会在适当的位置更改阵列以提高速度,但这不会导致错误,正如您在上面的工作中看到的那样
下面是我的代码,所以这是可复制的
我有以下文件:
测试步骤c:
#include <Python.h>
#include <numpy/arrayobject.h>
#include "structmember.h"
#include "add.h"
/* static PyObject *add(PyObject *self, PyObject *args); */
typedef struct {
PyObject_HEAD
PyObject *runs; /* run lengths */
} Rle;
static void
Rle_dealloc(Rle* self)
{
Py_XDECREF(self->runs);
Py_TYPE(self)->tp_free((PyObject*)self);
}
static PyObject *
Rle_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
printf("New was called! New was called! New was called!\n");
Rle *self;
PyObject *rs, *vs;
import_array();
if (!PyArg_ParseTuple(args, "O", &rs))
return NULL;
PyObject *runs = PyArray_FROM_OTF(rs, NPY_DOUBLE, NPY_IN_ARRAY);
self = (Rle *)type->tp_alloc(type, 0);
if (self != NULL) {
self->runs = runs;
if (self->runs == NULL) {
Py_DECREF(self);
return NULL;
}
}
printf("Reference count after new: %d\n", Py_REFCNT(self));
return (PyObject *)self;
}
static int
Rle_init(Rle *self, PyObject *args, PyObject *kwds)
{
printf("Init was called! Init was called! Init was called!\n");
printf("Reference count after init: %d\n", Py_REFCNT(self));
return 0;
}
static PyMemberDef Rle_members[] = {
{"runs", T_OBJECT_EX, offsetof(Rle, runs), 0,
"Run lengths"},
{NULL} /* Sentinel */
};
static PyObject * Rle_add(Rle* self)
{
int N = (int)PyArray_DIM(self->runs, 0);
double *x = (double*)PyArray_DATA(self->runs);
add(x, N);
return (PyObject *)self;
}
static PyMethodDef Rle_methods[] = {
{"add", (PyCFunction)Rle_add, METH_NOARGS,
"Add 1 to the runs"
},
{NULL} /* Sentinel */
};
static PyTypeObject RleType = {
PyVarObject_HEAD_INIT(NULL, 0)
"rle.Rle", /* tp_name */
sizeof(Rle), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)Rle_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_reserved */
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 */
"Rle objects", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
Rle_methods, /* tp_methods */
Rle_members, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)Rle_init, /* tp_init */
0, /* tp_alloc */
Rle_new, /* tp_new */
};
static PyModuleDef rletestmodule = {
PyModuleDef_HEAD_INIT,
"rletest",
"Example module that creates an extension type.",
-1,
NULL, NULL, NULL, NULL, NULL
};
PyMODINIT_FUNC
PyInit_rletest(void)
{
PyObject* m;
if (PyType_Ready(&RleType) < 0)
return NULL;
m = PyModule_Create(&rletestmodule);
if (m == NULL)
return NULL;
Py_INCREF(&RleType);
PyModule_AddObject(m, "Rle", (PyObject *)&RleType);
return m;
}
add.h
add.c:
#include <stdio.h>
void add(double *x, int N) {
int n;
for (n = 0; n < N; n++) {
x[n] += 1.0;
}
}
建造它
return (PyObject *)self;
您现在有了一个对self
的额外引用,因此需要incref
它。实际上,您不分配返回值,因此Python会立即减少它,并且r
不再存在
(您的工作区避免了立即执行decref
,但我很惊讶它只是在以后导致分段错误。)
您现在有了一个对self
的额外引用,因此需要incref
它。实际上,您不分配返回值,因此Python会立即减少它,并且r
不再存在
(您的工作区避免了立即执行decref
,但我很惊讶它只是在以后导致分段错误。)
void add(double *x, int N);
#include <stdio.h>
void add(double *x, int N) {
int n;
for (n = 0; n < N; n++) {
x[n] += 1.0;
}
}
python setup.py build_ext --inplace
return (PyObject *)self;