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



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

我写了一些代码,似乎有效。基本上,我只是在我的 ModPoly 结构中存储三个 PyObject*。现在我想添加多项式系数的存储。

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

没有"系数"的原始代码可以在这里找到。带有系数的代码在这里。

我希望你们中的某个人能告诉我我在这里做错了哪里。顺便说一下,也欢迎对代码发表评论。这是我的第一次延期,我知道我可能做得很糟糕。

正如 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,但我没有将其分配给自>ob_item。

-

脸掌-

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

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

相关内容

  • 没有找到相关文章

最新更新