Явный NUL-байт, необходимый в конце байтового массива для того, чтобы Cython мог преобразовать его в C-строку с нулевым символом в конце - PullRequest
0 голосов
/ 02 июня 2018

При преобразовании bytearray -объекта (или bytes -объекта в этом отношении) в C-строку, cython-документация рекомендует использовать следующее:

cdef char * cstr = py_bytearray

нет никаких служебных данных, поскольку cstr указывает на буфер объекта bytearray.

Однако строки C заканчиваются нулем и, следовательно,чтобы иметь возможность передавать cstr в C-функцию, она также должна заканчиваться нулем.Cython-документация не предоставляет никакой информации о том, заканчиваются ли получающиеся C-строки нулем.

Можно явно добавить NUL -байт к byarray -объекту, например, с помощьюиспользуя b'text\x00' вместо просто `b'text '.Все же это громоздко, легко забыть, и есть, по крайней мере, экспериментальные доказательства того, что явный NUL-байт не нужен:

%%cython
from libc.stdio cimport printf
def printit(py_bytearray):
    cdef char *ptr = py_bytearray
    printf("%s\n", ptr)

А теперь

printit(bytearray(b'text'))

печатает нужный«text» в stdout (который, в случае с IPython-ноутбуком, явно не выводится в браузере).

Но является ли это счастливым совпадением или есть гарантия, что буферобъект bytearray (или объект bytes) завершается нулем?

1 Ответ

0 голосов
/ 02 июня 2018

Я думаю, что это безопасно (по крайней мере, в Python 3), однако я бы немного насторожился.

Cython использует функцию C-API PyByteArray_AsString.Документация Python3 для него гласит: «К возвращаемому массиву всегда добавляется дополнительный нулевой байт». Python2 версия не имеет этой заметки, поэтому трудно быть уверенным, что это безопасно.

На практике, я думаю, Python справляется с этим, всегда перераспределяя байтовые массивы одним и заканчивая NULL.их (см. исходный код для одного примера того, где это сделано).

Единственная причина быть немного осторожной - это то, что она совершенно приемлема для байтовых массивов (и строк Python в этом отношении)содержать 0 байт в строке, так что это не хороший индикатор того, где находится конец.Следовательно, вы все равно должны использовать их len.(Это слабый аргумент, тем более что вы, вероятно, инициализируете их, так что вы знаете, должно ли это быть правдой)


(Моя первоначальная версия этого ответа содержала что-то вроде _PyByteArray_empty_string. @ead указал в комментариях, что я ошибся по этому поводу, и поэтому он отредактирован ...)

...