实现nb_inplace_add会导致返回只读缓冲区对象

时间:2012-08-10 07:58:58

标签: python python-c-api python-c-extension

我正在编写就地添加操作的实现。但是,出于某种原因,我有时会得到一个只读缓冲区(当我添加自定义扩展类和整数时...)。

相关代码是:

static PyObject *
ModPoly_InPlaceAdd(PyObject *self, PyObject *other)
{

    if (!ModPoly_Check(self)) {
        //Since it's in-place addition the control flow should never
        // enter here(I suppose)
        if (!ModPoly_Check(other)) {
            PyErr_SetString(PyExc_TypeError, "Neither argument is a ModPolynomial.");
            return NULL;
        }
        return ModPoly_InPlaceAdd(other, self);
    } else {
        if (!PyInt_Check(other) && !PyLong_Check(other)) {
            Py_INCREF(Py_NotImplemented);
            return Py_NotImplemented;
        }
    }

    ModPoly *Tself = (ModPoly *)self;
    PyObject *tmp, *tmp2;
    tmp = PyNumber_Add(Tself->ob_item[0], other);
    tmp2 = PyNumber_Remainder(tmp, Tself->n_modulus);

    Py_DECREF(tmp);
    tmp = Tself->ob_item[0];
    Tself->ob_item[0] = tmp2;
    Py_DECREF(tmp);
    return (PyObject *)Tself;

}

如果不是返回(PyObject*)Tself(或简称为“self”),而是引发异常,原始对象会正确更新[使用某些printf进行检查]。如果我使用Py_RETURN_NONE宏,它会正确地将ModPoly转换为None(在python端)。

我做错了什么?我正在返回一个指向ModPoly对象的指针,它怎么能成为一个缓冲区呢?而且我没有看到对这些指针的任何操作。

示例用法:

>>> from algebra import polynomials
>>> pol = polynomials.ModPolynomial(3,17)
>>> pol += 5
>>> pol
<read-only buffer ptr 0xf31420, size 4 at 0xe6faf0>

我尝试将返回行更改为:

printf("%d\n", (int)ModPoly_Check(self));
return self;

并在就地添加时打印1(意味着返回的值为ModPolynomial类型...)

1 个答案:

答案 0 :(得分:2)

根据the documentation,对象的inplace add操作返回一个新引用。

直接返回self而不调用Py_INCREF,您的对象在被引用时将被释放。如果某个其他对象被分配了同一块内存,那么这些引用现在将为您提供新对象。