我正在尝试为python编写C-Extension。我想写的是一个ModPolynomial类,它表示(Z / nZ)[x] / x ^ r-1上的多项式[即使你可能在不知道任何这样的多项式的情况下回答我的问题]。
我写了一些代码,似乎有用。基本上我只在我的ModPoly结构中存储了三个PyObject *。现在我想为多项式的系数添加存储空间。
因为我希望系数是只读的,所以我想通过PyGetSetDef添加一个getter / setter函数对。但是当我从python访问getter(例如print pol.coefficients)时,我收到了一个Segmentation Fault。
可以找到没有“系数”的原始代码here。 系数代码为here。
我希望你们中的某个人能告诉我这里我做错了什么。 顺便说一句,欢迎对代码发表评论。这是我的第一次扩展,我知道我可能做得非常糟糕。
正如ecatmur在评论中所说,PyVarObject在结构的末尾存储了一定数量的“槽”。所以我决定避开它们。
相关代码是:
typedef struct {
PyObject_HEAD
/* Type specific fields */
Py_ssize_t ob_size;
PyObject **ob_item;
Py_ssize_t allocated;
PyObject *r_modulus;
PyObject *n_modulus;
PyObject *degree;
} ModPoly;
static PyObject *
ModPoly_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
ModPoly *self;
self = (ModPoly *)type->tp_alloc(type, 0);
if (self != NULL) {
[...]
self->ob_size = 0;
self->ob_item = NULL;
self->allocated = 0;
}
return (PyObject *)self;
}
static int
ModPoly_init(ModPoly *self, PyObject *args, PyObject *kwds)
{
PyObject *r_modulus=NULL, *n_modulus=NULL, *coefs=NULL, *tmp;
PyObject **tmp_ar;
static char *kwlist[] = {"r_modulus", "n_modulus", "coefficients", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist,
&r_modulus, &n_modulus, &coefs))
return -1;
[...]
// The polynomial defaults to "x", so the coefficients should be [0, 1].
tmp_ar = (PyObject **)malloc(2 * sizeof(PyObject*));
if (tmp_ar == NULL) {
Py_DECREF(self->r_modulus);
Py_DECREF(self->n_modulus);
Py_DECREF(self->degree);
return -1;
}
tmp_ar[0] = PyInt_FromLong(0);
if (tmp_ar[0] != NULL) {
tmp_ar[1] = PyInt_FromLong(1);
}
if (tmp_ar[0] == NULL || tmp_ar[0] == NULL) {
Py_DECREF(self->r_modulus);
Py_DECREF(self->n_modulus);
Py_DECREF(self->degree);
Py_XDECREF(tmp_ar[0]);
Py_XDECREF(tmp_ar[1]);
free(tmp_ar);
return -1;
}
self->ob_size = 2;
self->allocated = 2;
return 0;
}
[...]
static PyObject *
ModPoly_getcoefs(ModPoly *self, void *closure)
{
printf("here"); // "here" is never printed
PyTupleObject *res=(PyTupleObject*)PyTuple_New(self->ob_size);
Py_ssize_t i;
PyObject *tmp;
if (res == NULL)
return NULL;
for (i=0; i < self->ob_size; i++) {
tmp = self->ob_item[i];
Py_INCREF(tmp);
PyTuple_SET_ITEM(res, i, tmp);
}
return (PyObject *)res;
}
static PyObject *
ModPoly_setcoefs(ModPoly *self, PyObject *value, void* closure)
{
PyErr_SetString(PyExc_AttributeError,
"Cannot set the coefficients of a polynomial.");
return NULL;
}
[...]
static PyGetSetDef ModPoly_getsetters[] = {
{"coefficients",
(getter)ModPoly_getcoefs, (setter)ModPoly_setcoefs,
"The polynomial coefficients.", NULL},
{NULL, 0, 0, NULL, NULL}
};
static PyTypeObject ModPolyType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
[...]
ModPoly_members, /* tp_members */
ModPoly_getsetters, /* tp_getset */
0, /* tp_base */
[...]
};
[...]
修改
我试图通过指令重新实现getter指令,我理解了我没做的事情。在ModPoly_init函数中,我创建了存储系数的tmp_ar,但是我没有将它分配给self-&gt; ob_item。
-facepalm -
答案 0 :(得分:2)
您似乎只是在ModPoly.ob_item
中分配给ModPoly_new()
(将其设置为NULL
)。
ModPoly_getcoefs()
然后取消引用空指针,这将为您提供段错误。您似乎打算在ob_item
中分配给ModPoly_init()
,但实际上并没有这样做。