2012-08-10 64 views
0

我正在編寫就地添加操作的實現。但是,出於某種原因,我有時會得到一個只讀緩衝區(當我添加一個自定義擴展類和一個整數時...)。實現nb_inplace_add導致返回只讀緩衝區對象

相關的代碼是:

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(或簡稱「自我」),我拋出一個異常,原來的對象得到正確更新[使用一些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

根據the documentation,對象的就地添加操作返回一個新的引用。

通過直接返回self而不需要調用Py_INCREF就可以了,當它仍然被引用時,你的對象將被釋放。如果某個其他對象被分配了相同的內存塊,則這些引用現在將爲您提供新對象。

+0

你說得對。這是我的第一個C擴展,因此我仍然試圖瞭解何時應該使用INCREF/DECREF。 – Bakuriu 2012-08-10 09:17:34