Python: как упаковать различные типы данных в строковый буфер, используя struct.pack_into

Я пытаюсь упаковать некоторые неподписанные данные int в строковый буфер, созданный с помощью ctypes.create_string_buffer.

Вот следующий сегмент кода и пример, показывающий ошибку в кодедексе:

import struct
import ctypes
import binascii

buf = ctypes.create_string_buffer(16)
struct.pack_into("=I=I=I", buf, 0, 1, 2, 3)
print binascii.hexlify(buf)

Это приводит к следующей ошибке:

...
struct.error: bad char in struct format

В документации не упоминается, можете ли вы упаковывать данные разных типов, если базовый буфер имеет определенный тип C. В этом случае, пытаясь упаковать неподписанные данные int в строковый буфер с базовым типом c_char. Кто-нибудь знает о решении для этого или существует конкретный способ создания буфера, который может упаковывать данные любого типа?

Ответ 1

Вы не должны префикс каждого спецификатора вывода кодом '='. Просто скажите это один раз:

struct.pack_into("=III", buf, 0, 1, 2, 3)

Это дает:

01000000020000000300000000000000

Ответ 2

Извините за воскрешение старой темы, но я получаю смысл "привязки" - попадания, вероятно, аналогичной фоновой привычки.

"первый символ строки формата может использоваться для указания порядка байтов, размера и выравнивания упакованных данных" Я согласен. Однако:

  • Документы Python преднамеренно (?) опускают даже один пример использования форматировщиков заказов (все примеры предполагают собственный порядок байтов, размер и выравнивание с машиной большого конца.)
  • Можно предположить (как я, и, вероятно, хватал), что "III" состоит из трех строк форматирования, и мы можем форматировать каждый из них по желанию. Следовательно, =I=I=I. Я выстрелил себе в ногу после привыкания к Ruby array.pack, где можно свободно изменять порядок вдоль выражения (эквивалент Ruby I_I_I_ в этом случае, поскольку селектор заказов приходит после типа).

Следовательно, возможно, было бы неплохо добавить несколько строк в struct.pack/unpack docs, давая примеры использования порядка и дополнений (meh, padding ударил меня еще сильнее... Я мог жить с собственным заказом, но отступы разрушил мой протокол).

Ответ 3

Стандартная рабочая процедура: прочитайте сообщение об ошибке.

"bad char в формате структуры" означает, что он говорит.

Стандартная рабочая процедура: проверьте документы. Здесь в нем говорится: "Первый символ [мой акцент] строки формата может использоваться для указания порядка байтов, размера и выравнивания упакованных данных" и далее перечисляет = как возможность. В следующем разделе (Форматы символов) перечислены многие буквы, включая I.

Заключение: ваша строка формата должна быть "=III".

Примечание. Проблема не имеет ничего общего с целевым буфером, не говоря уже о ее базовом типе C:

>>> import struct
>>> struct.pack("=I=I=I", 1, 2, 3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
struct.error: bad char in struct format
>>> struct.pack("=III", 1, 2, 3)
'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'
>>>