справочник по Python. мм isbn 9785932861578 9 785932 861578
Скачать 4.21 Mb.
|
745 Э ти спецификаторы должны использоваться только для обработки строк байтов и не способны работать со строками Юникода. Спецификатор “y” может принимать только строки байтов, не содержащие символы NULL. В табл. 26.3 перечислены спецификаторы, которые принимают произволь- ные объекты языка Python и возвращают результат типа PyObject *. Они иногда используются в расширениях на языке C, которые должны обра- C, которые должны обра- , которые должны обра- батывать объекты языка Python, более сложные, чем простые числа или строки, такие как экземпляры классов или словари. Таблица 26.3. Преобразование объектов языка Python и соответствующие типы аргументов функций PyArg_Parse* Формат Тип в языке Python Тип аргумента в языке C “O” Любой PyObject ** r “O!” Любой PyTypeObject * type, PyObject **r “O&” Любой int (* converter)(PyObject *, void *), void *r “S” Строка PyObject ** r “U” Строка Юникода PyObject ** r Спецификаторы “O”, “S” и “U” возвращают объекты Python типа PyObject *. Спецификаторы “S” и “U” ограничиваются объектами строк и строк Юни- кода соответственно. Спецификатор “O!” требует наличия двух аргументов: указателя на объект типа языка Python и указателя PyObject * на указатель, который ссылается на местоположение объекта в памяти. Если тип объекта не соответствует объекту типа, возбуждается исключение TypeError. Например: /* Преобразование списка аргументов */ PyObject *listobj; PyArg_ParseTuple(args,”O!”, &PyList_Type, &listobj); В следующем списке перечислены имена типов языка C, соответствующие некоторым контейнерным типам в языке Python, которые часто участвуют в подобных преобразованиях. Имя типа в языке C Тип в языке Python PyList_Type list PyDict_Type dict PySet_Type set PyFrozenSet_Type frozen_set PyTuple_Type tuple PySlice_Type slice PyByteArray_Type bytearray 746 Глава 26. Расширение и встраивание интерпретатора Python Спецификатор “O&” принимает два аргумента (converter, addr) и преобразует PyObject * в тип данных языка C. Аргумент converter – это указатель на функцию с сигнатурой int converter(PyObject *obj, void *addr), где obj – это полученный объект на языке Python, а addr – адрес, который передается вторым аргументом функции PyArg_ParseTuple(). В случае успеха функция converter() должна возвращать 1, и 0 – в случае ошибки. Кроме того, в слу- чае ошибки функция converter() должна возбудить исключение. Преобразо- вания такого типа могут использоваться для отображения объектов языка Python, таких как списки или кортежи, в структуры данных на языке C. Например, ниже приводится одна из возможных реализаций функции- обертки py_distance() из ранее рассматривавшегося программного кода: /* Преобразует кортеж в структуру Point. */ int convert_point(PyObject *obj, void *addr) { Point *p = (Point *) addr; return PyArg_ParseTuple(obj,”ii”, &p->x, &p->y); } PyObject *py_distance(PyObject *self, PyObject *args) { Point p1, p2; double result; if (!PyArg_ParseTuple(args,”O&O&”, convert_point, &p1, convert_point, &p2)) { return NULL; } result = distance(&p1,&p2); return Py_BuildValue(“d”,result); } Наконец, аргумент format может содержать дополнительные модификато- ры, имеющие отношение к распаковыванию кортежей, строкам докумен- тирования, сообщениям об ошибках и значениям аргументов по умолча- нию. Эти модификаторы перечислены в следующем списке: Формат Описание “(items)” Описывает порядок распаковывания кортежей объектов. items содер- жит спецификаторы формата. “|” Начало списка необязательных аргументов. “:” Конец списка аргументов. Остальной текст обозначает имя функции. “;” Конец списка аргументов. Остальной текст – это сообщение об ошибке. Модификатор “(items)” распаковывает значения, переданные в виде кор- тежа языка Python. Это может пригодиться для отображения кортежей в простые структуры на языке C. Например, ниже приводится еще одна возможная реализация функции-обертки py_distance(): PyObject *py_distance(PyObject *self, PyObject *args) { Point p1, p2; double result; if (!PyArg_ParseTuple(args,”(dd)(dd)”, &p1.x, &p1.y, &p2.x, &p2.y)) { Модули расширений 747 return NULL; } result = distance(&p1,&p2); return Py_BuildValue(“d”,result); } М одификатор “|” указывает, что все последующие аргументы являются необязательными. Этот модификатор может появляться в строке формата только один раз и не может быть вложенным. Модификатор “:” отмечает конец списка аргументов. Любой текст, следующий за ним, будет интер- претироваться, как имя функции для вывода в сообщениях об ошибках. Модификатор “;” также отмечает конец списка аргументов. Любой текст, следующий за ним, будет интерпретироваться, как текст сообщения об ошибке. Имейте в виду, что допускается использовать только какой-то один из модификаторов : и ;. Ниже приводятся несколько примеров: PyArg_ParseTuple(args,”ii:gcd”, &x, &y); PyArg_ParseTuple(args,”ii; gcd requires 2 integers”, &x, &y); ёёё /* Преобразование с двумя необязательными аргументами */ PyArg_ParseTuple(args,”s|s”, &buffer, &delimiter); Преобразование типов данных языка C в типы языка Python Для преобразования значений переменных языка C в объекты языка Py- C в объекты языка Py- в объекты языка Py- Py- thon используется следующая функция: PyObject *Py_BuildValue(char *format, ...) Конструирует объект Python на основе последовательности переменных языка C. Аргумент format – это строка, описывающая требуемое преобра- зование. Остальные аргументы функции – значения переменных языка C, участвующие в преобразовании. Спецификаторы формата, которые можно использовать в аргументе format, похожи на спецификаторы, используемые в функциях PyArg_ParseTuple*(), как видно из табл. 26.4. Таблица 26.4. Спецификаторы формата для функции Py_BuildValue() Формат Тип в языке Python Тип в языке C Описание “” None void Ничего. “a” Строка char * Строка, завершающаяся сим- волом NULL. Если указатель на строку содержит значение NULL , возвращает значение None. “s#” Строка char * , int Строка и ее длина. Может содер- жать байты со значением ‘\x00’. Если указатель на строку содер- жит значение NULL , возвращает значение None. 748 Глава 26. Расширение и встраивание интерпретатора Python Формат Тип в языке Python Тип в языке C Описание “y” Строка байтов char * То же, что и “s”, но возвращает строку байтов. “y#” Строка байтов char * , int То же, что и “s#”, но возвращает строку байтов. “z” Строка или None char * То же, что и “s”. “z#” Строка или None char * , int То же, что и “s#”. “u” Строка Юникода Py_UNICODE * Строка Юникода, завершаю- щаяся символом NULL. Если указатель на строку содержит значение NULL , возвращает зна- чение None. “u#” Строка Юникода Py_UNICODE * Строка Юникода и ее длина. “U” Строка Юникода char * Преобразует строку языка C, завершающуюся символом NULL, в строку Юникода. “U#” Строка Юникода char * , int Преобразует строку языка C в строку Юникода. “b” Целое число char 8-битное целое. “B” Целое число unsigned char 8-битное целое без знака. “h” Целое число short 16-битное короткое целое. “H” Целое число unsigned short 16-битное короткое целое без знака. “i” Целое число int Целое число. “I” Целое число unsigned int Целое число без знака. “l” Целое число long Длинное целое число. “L” Целое число unsigned long Длинное целое число без знака. “k” Целое число long long Длинное целое типа long long. “K” Целое число unsigned long long Длинное целое типа long long без знака. “n” Целое число Py_ssize_t Тип size в языке Python. “c” Строка char Единственный символ. Создает строку языка Python с одним символом. “f” Число с плавающей точкой float Число с плавающей точкой оди- нарной точности. “d” Число с плавающей точкой double Число с плавающей точкой двойной точности. “D” Комплексное число Py_complex Комплексное число. Таблица 26.4 (продолжение) Модули расширений 749 Формат Тип в языке Python Тип в языке C Описание “O” Л юбой PyObject * Любой объект языка Python. Объект не изменяется, за ис- ключением его счетчика ссы- лок, который увеличивается на 1. Если передается пустой указатель, возвращает также пустой указатель. Это удобно, когда ошибка возникла где-то в одном месте, а в другом необ- ходимо продолжить ее распро- странение. “O&” Любой функция пре- пре- пре- образования, любой Данные, полученные от про- граммного кода на языке C, обрабатываются функцией пре- образования. “S” Строка PyObject * То же, что и “O”. “N” Любой PyObject * То же, что и “O”, за исключением того, что счетчик ссылок объек- та не увеличивается. “( items)” Кортеж vars Создает кортеж элементов items. items – строка со спецификато- рами формата из этой таблицы. vars – список переменных языка C, соответствующих специфика- , соответствующих специфика- торам в items. “[ items]” Список vars Создает список элементов items. items – строка со спецификато- рами формата. vars – список переменных языка C, соот- ветствующих спецификаторам в items. “{ items}” Словарь vars Создает словарь элементов items. Ниже приводятся несколько примеров создания значений различных ти- пов: Py_BuildValue(“”) None Py_BuildValue(“i”,37) 37 Py_BuildValue(“ids”,37,3.4,”hello”) (37, 3.5, “hello”) Py_BuildValue(“s#”,”hello”,4) “hell” Py_BuildValue(“()”) () Py_BuildValue(“(i)”,37) (37,) Py_BuildValue(“[ii]”,1,2) [1,2] Py_BuildValue(“[i,i]”,1,2) [1,2] Py_BuildValue(“{s:i,s:i}”,”x”,1,”y”,2) {‘x’:1, ‘y’:2} Строки Юникода создаются из данных типа char *; это означает, что ис- ходные данные представляют собой последовательность байтов в коди- ровке по умолчанию (обычно UTF-8). Данные автоматически декодируют- (обычно UTF-8). Данные автоматически декодируют- обычно UTF-8). Данные автоматически декодируют- UTF-8). Данные автоматически декодируют- Данные автоматически декодируют- 750 Глава 26. Расширение и встраивание интерпретатора Python ся в строки Юникода при передаче программному коду на языке Python. Единственное исключение из этого правила составляют спецификаторы “y” и “y#”, которые возвращают обычные строки байтов. Добавление значений в модуль В функции инициализации модуля расширения часто производится до- бавление констант и других значений. Для этой цели могут использоваться следующие функции: int PyModule_AddObject(PyObject *module, const char *name, PyObject *value) Добавляет в модуль новое значение. Аргумент name определяет имя значе- ния, а аргумент value – объект Python, содержащий значение. Значения можно создавать с помощью функции Py_BuildValue(). int PyModule_AddIntConstant(PyObject *module, const char *name, long value) Добавляет в модуль целочисленное значение. void PyModule_AddStringConstant(PyObject *module, const char *name, const char *value) Добавляет в модуль строковое значение. В аргументе value должна переда- ваться строка, заканчивающаяся символом NULL. void PyModule_AddIntMacro(PyObject *module, macro) Добавляет в модуль целочисленное значение макроопределения. Аргумент macro должен быть именем макроопределения препроцессора. void PyModule_AddStringMacro(PyObject *module, macro) Добавляет в модуль строковое значение макроопределения. Обработка ошибок Модули расширений сообщают об ошибках, возвращая интерпретатору значение NULL. Перед тем как вернуть NULL, модуль должен определить ис- ключение с помощью одной из следующих функций: void PyErr_NoMemory() Возбуждает исключение MemoryError. void PyErr_SetFromErrno(PyObject *exc) Возбуждает исключение exc. В аргументе exc передается объект исключе- ния. Код ошибки для исключения извлекается из переменной errno в би- блиотеке языка C. void PyErr_SetFromErrnoWithFilename(PyObject *exc, char *filename) То же, что и PyErr_SetFromErrno(), но добавляет в исключение еще и имя фай- ла. void PyErr_SetObject(PyObject *exc, PyObject *val) Возбуждает исключение exc. В аргументе exc передается объект исключе- ния, а в аргументе val – объект со значениями атрибутов исключения. Модули расширений 751 void PyErr_SetString(PyObject *exc, char *msg) Возбуждает исключение exc. В аргументе exc передается объект исключе- ния, а в аргументе msg – сообщение, описывающее ошибку. В аргументе exc допускается передавать одно из следующих значений: Имя в языке C Исключение в языке Python PyExc_ArithmeticError ArithmeticError PyExc_AssertionError AssertionError PyExc_AttributeError AttributeError PyExc_EnvironmentError EnvironmentError PyExc_EOFError EOFError PyExc_Exception Exception PyExc_FloatingPointError FloatingPointError PyExc_ImportError ImportError PyExc_IndexError IndexError PyExc_IOError IOError PyExc_KeyError KeyError PyExc_KeyboardInterrupt KeyboardInterrupt PyExc_LookupError LookupError PyExc_MemoryError MemoryError PyExc_NameError NameError PyExc_NotImplementedError NotImplementedError PyExc_OSError OSError PyExc_OverflowError OverflowError PyExc_ReferenceError ReferenceError PyExc_RuntimeError RuntimeError PyExc_StandardError StandardError PyExc_StopIteration StopIteration PyExc_SyntaxError SyntaxError PyExc_SystemError SystemError PyExc_SystemExit SystemExit PyExc_TypeError TypeError PyExc_UnicodeError UnicodeError PyExc_UnicodeEncodeError UnicodeEncodeError PyExc_UnicodeDecodeError UnicodeDecodeError PyExc_UnicodeTranslateError UnicodeTranslateError 752 Глава 26. Расширение и встраивание интерпретатора Python Имя в языке C Исключение в языке Python PyExc_ValueError ValueError PyExc_WindowsError WindowsError PyExc_ZeroDivisionError ZeroDivisionError Н иже перечислены функции, которые могут использоваться для полу- чения от интерпретатора информации о наличии исключения или чтобы сбросить исключение: void PyErr_Clear() Сбрасывает ранее возбужденные исключения. PyObject *PyErr_Occurred() Проверяет, было ли возбуждено исключение. Если исключение было воз- буждено, возвращает текущее значение исключения. В противном случае возвращает NULL. int PyErr_ExceptionMatches(PyObject *exc) Проверяет, соответствует ли текущее исключение исключению exc. Если соответствует, возвращает 1, если не соответствует – 0. При сопоставлении исключений эта функция применяет правила, определяемые языком Py- Py- thon. То есть exc может быть суперклассом текущего исключения или кор- тежем классов исключений. Ниже приводится пример реализации блока try-except на языке C: /* Выполнить некоторые операции над объектами языка Python */ if (PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_ValueError)) { /* выполнить действия по восстановлению после ошибки */ ... PyErr_Clear(); return result; /* Допустимый PyObject * */ } else { return NULL; /* Передать исключение интерпретатору */ } } Подсчет ссылок В отличие от программ, написанных на языке Python, расширения на язы- Python, расширения на язы- , расширения на язы- ке C имеют возможность манипулировать счетчиками ссылок объектов Py- C имеют возможность манипулировать счетчиками ссылок объектов Py- имеют возможность манипулировать счетчиками ссылок объектов Py- Py- thon. Делается это с помощью следующих макроопределений, каждое из которых применяется к объектам типа PyObject *. Макроопределение Описание Py_INCREF( obj) Увеличивает счетчик ссылок объекта, на который ссылает- ся указатель obj. Указатель не должен быть пустым. (продолжение) Модули расширений 753 Py_DECREF( obj) У меньшает счетчик ссылок объекта, на который ссылается указатель obj. Указатель не должен быть пустым. Py_XINCREF( obj) Увеличивает счетчик ссылок объекта, на который ссылает- ся указатель obj. Указатель может быть пустым. Py_XDECREF( obj) Уменьшает счетчик ссылок объекта, на который ссылается указатель obj. Указатель может быть пустым. Манипулирование счетчиками ссылок объектов языка Python из про- Python из про- из про- граммного кода на языке C – это достаточно тонкая тема, поэтому читате- C – это достаточно тонкая тема, поэтому читате- – это достаточно тонкая тема, поэтому читате- лям настоятельно рекомендуется прочитать документ «Extending and Em- Extending and Em- and Em- and Em- Em- Em- bedding the Python Interpreter» (Расширение и встраивание интерпретато- the Python Interpreter» (Расширение и встраивание интерпретато- the Python Interpreter» (Расширение и встраивание интерпретато- Python Interpreter» (Расширение и встраивание интерпретато- Python Interpreter» (Расширение и встраивание интерпретато- Interpreter» (Расширение и встраивание интерпретато- Interpreter» (Расширение и встраивание интерпретато- » (Расширение и встраивание интерпретато- ра Python), по адресу http://docs.python.org/extending, прежде чем предпри- нимать что-либо. Как правило, в расширениях на языке C не приходится беспокоиться о счетчиках ссылок на объекты, за исключением следующих случаев: • Если ссылка на объект Python сохраняется для последующего исполь- Python сохраняется для последующего исполь- сохраняется для последующего исполь- зования в структуре на языке C, счетчик ссылок необходимо увеличить. • Аналогично при удалении ссылки, сохраненной ранее, счетчик ссылок необходимо уменьшить. • При управлении контейнерными объектами языка Python (списками, словарями и другими) из программного кода на языке C может потребо- C может потребо- может потребо- ваться реализовать управление счетчиками ссылок отдельных элемен- тов. Например, высокоуровневые операции, которые извлекают или до- бавляют элементы в контейнер, обычно увеличивают счетчик ссылок. Обычно ошибки при работе со счетчиками ссылок проявляются в аварий- ном завершении интерпретатора при попытке использовать расширение (вы забыли увеличить счетчик ссылок) или в виде утечек памяти при исполь- зовании функций из расширения (вы забыли уменьшить счетчик ссылок). |