Строки Unicode, передаваемые в библиотеки C
Учитывая, что кто-то хочет написать модуль расширения, который должен передавать строку Python в библиотечную функцию C. Итак, возникает вопрос, как правильно обрабатывать Unicode. Итак, одна из основных возникающих проблем заключается в том, что существующие библиотеки C не понимают собственного представления Unicode в Python. Следовательно, основная задача - преобразовать строку Python в форму, более понятную для библиотек C.
Чтобы проиллюстрировать решение - ниже приведены две функции C, которые работают со строковыми данными и выводят их для отладки и экспериментов.
Code #1 : Uses bytes provided in the form char *, int
void print_chars( char *s, int len) { int n = 0; while (n < len) { printf ( "%2x " , (unsigned char ) s[n]); n++; } printf ( "
" ); } |
Code #2 : Uses wide characters in the form wchar_t *, int
void print_wchars( wchar_t *s, int len) { int n = 0; while (n < len) { printf ( "%x " , s[n]); n++; } printf ( "
" ); } |
Python strings need to be converted to a suitable byte encoding such as UTF-8 for the byte-oriented function print_chars()
. The code given below a simple extension function solving the purpose.
Code #3 :
static PyObject *py_print_chars(PyObject *self, PyObject *args) { char *s; Py_ssize_t len; if (!PyArg_ParseTuple(args, "s#" , &s, &len)) { return NULL; } print_chars(s, len); Py_RETURN_NONE; } |
For library functions that work with the machine native wchar_t
type, C extension code can be written as –
Code #4 :
static PyObject * py_print_wchars(PyObject * self , PyObject * args) { wchar_t * s; Py_ssize_t len ; if (! PyArg_ParseTuple(args, "u#" , &s, & len )) { return NULL; } print_wchars(s, len ); Py_RETURN_NONE; } |
Теперь приведенный ниже код проверяет, как работают функции расширения.
It is to be observed the way the byte-oriented function print_chars()
is receiving UTF-8 encoded data, whereas print_wchars()
is receiving the Unicode code point values.
Code #5 :
s = "Spicy Jalapeu00f1o" print (print_chars(s)) print ( "
" , print_wchars(s)) |
Output :
53 70 69 63 79 20 4a 61 6c 61 70 65 c3 b1 6f 53 70 69 63 79 20 4a 61 6c 61 70 65 f1 6f
Давайте проверим природу библиотеки C. Для многих библиотек C может иметь смысл передавать байты вместо строки. Для этого воспользуемся приведенным ниже кодом преобразования.
Code #6 :
static PyObject *py_print_chars(PyObject *self, PyObject *args) { char *s; Py_ssize_t len; // accepts bytes, bytearray, or other byte-like object if (!PyArg_ParseTuple(args, "y#" , &s, &len)) { return NULL; } print_chars(s, len); Py_RETURN_NONE; } |
If still desire to pass strings, it is to be taken care that Python3 uses an adaptable string representation that is not entirely straightforward to map directly to C libraries using the standard types char *
or wchar_t *
. Thus, in order to present string data to C, some kind of conversion is almost always necessary. The s# and u# format codes to PyArg_ParseTuple()
safely perform such conversions.
Whenever a conversion is made, a copy of the converted data is attached to the original string object so that it can be reused later as shown in the code below.
Code #7 :
import sys s = "Spicy Jalapeu00f1o" print ( "Size : " , sys.getsizeof(s)) print ( "
" , print_chars(s)) print ( "
Size : " , sys.getsizeof(s)) print ( "
" , print_wchars(s)) print ( "
Size : " , sys.getsizeof(s)) |
Выход :
Размер: 87 53 70 69 63 79 20 4a 61 6c 61 70 65 c3 b1 6f Размер: 103 53 70 69 63 79 20 4a 61 6c 61 70 65 f1 6f Размер: 163
Внимание компьютерщик! Укрепите свои основы с помощью базового курса программирования Python и изучите основы.
Для начала подготовьтесь к собеседованию. Расширьте свои концепции структур данных с помощью курса Python DS. А чтобы начать свое путешествие по машинному обучению, присоединяйтесь к курсу Машинное обучение - базовый уровень.