2012-08-10 5 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

 Смежные вопросы

  • Нет связанных вопросов^_^