Отказ от ответственности: этот пост является спекуляцией, основанной на моем понимании «разделения труда» в Python stdlib, а не на фактической справочной информации.
Ваш вопрос проистекает из того факта, что «структуры C» и «двоичные данные», как правило, используются взаимозаменяемо, что, хотя и правильно на практике, неверно в техническом смысле. Документация struct
также вводит в заблуждение: она утверждает, что работает над "структурами C", в то время как лучшим описанием были бы "двоичные данные" с некоторыми оговорками об совместимости с Си.
По сути, struct
, array
и ctypes
делают разные вещи . struct
имеет дело с преобразованием значений Python в двоичные форматы в памяти. array
имеет дело с эффективным хранением большого количества значений. ctypes
имеет дело с языком C (*). Перекрытие в функциональности связано с тем фактом, что для C «двоичные форматы в памяти» являются собственными, а «эффективное хранение значений» означает упаковку их в массив, подобный C.
Вы также заметите, что struct
позволяет вам легко указывать порядковый номер, потому что он имеет дело с упаковкой и распаковкой двоичных данных многими различными способами, которыми они могут быть упакованы; в то время как в ctypes
труднее получить не собственный порядок байтов, потому что он использует порядок байтов , который является родным для C .
Если ваша задача - чтение бинарных структур данных, уровни абстракции возрастают:
- Разделение байтового массива вручную и преобразование частей с помощью
int.from_bytes
и т. П.
- Описание данных в виде строки формата и использование
struct
для распаковки за один раз
- Использование библиотеки типа Construct для декларативного описания структуры в логических терминах.
ctypes
здесь даже не фигурируют, потому что для этой задачи использование ctypes
в значительной степени требует двустороннего обхода другого языка программирования . Тот факт, что это работает так же хорошо для вашего примера, является случайным; это работает, потому что C изначально подходит для выражения многих способов упаковки двоичных данных. Но если бы ваша структура была, например, со смешанным порядком байтов, это было бы очень трудно выразить в ctypes
. Другим примером является float с половинной точностью, который не имеет эквивалента C (см. здесь ).
В этом смысле также очень разумно, чтобы ctypes
использовал struct
- в конце концов, "упаковка и распаковка двоичных данных" - это подзадача "взаимодействия с C".
С другой стороны, struct
не имеет смысла использовать ctypes
: это все равно, что использовать библиотеку email
для преобразования кодировки символов, потому что это задача, которую может выполнять библиотека электронной почты.
(*) ну в принципе. Более точным было бы что-то вроде «сред на основе C», то есть того, как современные компьютеры работают на низком уровне благодаря коэволюции с C в качестве основного языка систем.