Ограничения PyTuple_SetItem

У меня есть модуль расширения Python, который создает кортеж как атрибут другого объекта и устанавливает элементы в кортеж. Всякий раз, когда я выполняю этот модуль в Python, я получаю сообщение об ошибке SystemError: плохой аргумент внутренней функции

. Прочитав документы для PyTuple и отладив свою программу в течение нескольких часов, я все еще не мог понять, что, черт возьми, происходит. Запуск моей программы через отладчик показал, что проблема возникла при вызове библиотеки внутри интерпретатора Python. Итак, наконец, я взглянул на исходный код Python и наконец осознал проблему. Функция PyTuple_SetItem имеет интересное ограничение, о котором я не знал, и не могу найти явно задокументированных.

Вот важная функция в исходном коде Python (отредактирована для ясности):

int PyTuple_SetItem(register PyObject *op, register Py_ssize_t i, PyObject *newitem)
{
    .....
    if (!PyTuple_Check(op) || op->ob_refcnt != 1) {
        Py_XDECREF(newitem);
        PyErr_BadInternalCall();
        return -1;
    }
    .....
}

Важной строкой здесь является условие op-> ob_refcnt! = 1 . Итак, проблема: вы даже не можете вызвать PyTuple_SetItem , если у Tuple нет счетчика ссылок 1. Похоже, идея здесь в том, что вы никогда не должны использовать PyTuple_SetItem за исключением случаев, когда вы создаете кортеж с помощью PyTuple_New () . Я думаю, это имеет смысл, поскольку в конце концов кортежи должны быть неизменяемыми, поэтому это ограничение помогает сохранить ваш код C в большей степени в соответствии с абстракциями системы типов Python.

Однако я нигде не могу найти это ограничение, задокументированное. Соответствующие документы, похоже, здесь и здесь , ни один из них не указывает это ограничение. Документы в основном говорят, что когда вы вызываете PyTuple_New (X) , все элементы в кортеже инициализируются значением NULL . Поскольку NULL не является допустимым значением Python, программист модуля расширения должен убедиться, что все слоты в кортеже заполнены правильными значениями Python, прежде чем возвращать кортеж интерпретатору. Но нигде не сказано, что это нужно делать, пока объект Tuple имеет счетчик ссылок 1.

Итак, проблема в том, что я в основном закодировал себя в угол, потому что я не знал об этом. (недокументированное?) ограничение на PyTuple_SetItem . Мой код структурирован таким образом, что он Очень неудобно вставлять элементы в кортеж до тех пор, пока после сам кортеж не станет атрибутом другого объекта. Итак, когда приходит время заполнить элементы в кортеже, кортеж уже имеет большее количество ссылок.

Мне, вероятно, придется реструктурировать свой код, но я серьезно рассматривал возможность просто временно установить счетчик ссылок для Кортеж до 1, вставка элементов и восстановление исходного счетчика ссылок. Конечно, я знаю, что это ужасный взлом, и это не какое-то постоянное решение. Тем не менее, я хотел бы знать, документировано ли где-либо требование относительно количества ссылок в Tuple. Это просто деталь реализации CPython, После выполнения приложения я получил ключ приложения и apid с сервера. Но когда я открываю свою учетную запись в Городе ...

Я завершил код на стороне клиента, загрузив образец из git для push-уведомления в Android. После выполнения приложения я получил ключ приложения и apid с сервера. Но когда я открывал свою учетную запись в Urban Airship, я обнаружил следующие данные, согласно которым мое приложение не зарегистрировало ни одного приложения. enter image description here

Что делать теперь? Любая помощь будет принята с благодарностью

12
задан Jaydeep Khamar 31 May 2011 в 11:13
поделиться