0

Python用のC拡張機能を作成しようとしています。私が書きたいのは、(Z / nZ)[x] / x ^ r-1の多項式を表すModPolynomialクラスです[そのような多項式について何も知らなくても、私の質問に答えることができますが]。

私はいくつかのコードを書きましたが、それはうまくいくようです。基本的に、ModPoly構造に3つのPyObject*を格納するだけです。ここで、多項式の係数のストレージを追加したいと思います。

係数を読み取り専用にしたいので、PyGetSetDefを介してゲッター/セッター関数のペアを追加したいと思います。しかし、Pythonからゲッターにアクセスすると(たとえば、print 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 */
    [...]
};

[...]

編集

ゲッターの指示を指示ごとに再実装しようとしましたが、自分が何をしていないのか理解しました。ModPoly_init関数で、係数を格納するtmp_arを作成しますが、self->ob_itemには割り当てません。

-facepalm-

4

1 に答える 1

2

に割り当てているようですModPoly.ob_item(にModPoly_new()設定しますNULL)。

ModPoly_getcoefs()次に、nullポインターを逆参照します。これにより、セグメンテーション違反が発生します。に割り当てるつもりだったようですob_itemModPoly_init()、実際にはそうすることを避けてください。

于 2012-08-10T07:50:48.160 に答える