gpt4 book ai didi

通过 tp_getset 访问时 Python C 扩展出现段错误

转载 作者:行者123 更新时间:2023-11-30 14:24:21 24 4
gpt4 key购买 nike

我正在尝试为 python 编写一个 C 扩展。我想写的是一个 ModPolynomial 类,它表示 (Z/nZ)[x]/x^r-1 上的多项式[即使您可能在不了解此类多项式的情况下回答我的问题]。

我写了一些代码,看起来可行。基本上我只是在我的 ModPoly 结构中存储三个 PyObject* 。现在我想添加多项式系数的存储。

由于我希望系数是只读的,因此我想通过 PyGetSetDef 添加一对 getter/setter 函数。但是当我从 python 访问 getter 时(例如 print pol.coefficients),我收到了段错误。

原始代码,没有“系数”可以找到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->ob_item。

-捂脸-

最佳答案

您似乎只在 ModPoly_new() 中分配给 ModPoly.ob_item(将其设置为 NULL)。

ModPoly_getcoefs() 然后取消引用空指针,这会给您带来段错误。看起来您打算在 ModPoly_init() 中分配给 ob_item,但实际上并没有抽出时间这样做。

关于通过 tp_getset 访问时 Python C 扩展出现段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11883550/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com