LINUX.ORG.RU

python ctypes structure


0

1

есть структура. теоретически должна уместится в 32 бита, т.е. в int32.

class header(ctypes.Structure):
	# _pack_ = 1
	_fields_ = [
		('filedA', ctypes.c_ubyte, 3),
		('fieldB', ctypes.c_ubyte, 6),
		('fieldC', ctypes.c_uint32, 13),
		('fieldD', ctypes.c_uint32, 9)
	]

Но на деле получаем

aa = header()
ctypes.sizeof(aa)
5

еще интересней, когда заменяем в классе поля C и D на c_uint16, в результате размер = 6.

директива _pack_ тут не помогает, проверено.

вопрос - почему не укладывается структура в 4 байта?

Deleted

сейчас затестил,

h = header()
h.fieldD = 509
h.fieldA = 7
h.fieldB = 59
h.fieldC = 6839

f = open('/tmp/tst','wb')
f.write(h)
f.close()

на выходе файл размером в 5 байт. заглядываем внутрь и видим (в hex):

00 f6 5b dd 1f
первый байт нулевой. нафига он его аллокейтил для структуры, если она умещается в 4 байта?

Deleted
()

удивительное дело. выставил всем одинаковый тип c_uint32

class header(ctypes.Structure):
	_pack_ = 0
	_fields_ = [
		('fieldA', ctypes.c_uint32, 3),
		('fieldB', ctypes.c_uint32, 6),
		('fieldC', ctypes.c_uint32, 13),
		('fieldD', ctypes.c_uint32, 9)
	]

тестируем в питоновском шелле

>>> print header.fieldA
<Field type=c_uint, ofs=0:0, bits=3>
>>> print header.fieldB
<Field type=c_uint, ofs=0:3, bits=6>
>>> print header.fieldC
<Field type=c_uint, ofs=0:9, bits=13>
>>> print header.fieldD
<Field type=c_uint, ofs=0:22, bits=9>
>>> ctypes.sizeof(header())
4

это какой-то мейджик. все оффсеты встали на свое место и размер стал каким и должет быть. диво дивное, чудеса чудесные.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от anonymous

разумеется выравнивание. первый, потому как литлэндиан.

кстати, эйфория что «все заработало» была короткой. добавление поля с одним битом опять «выравнивает» по каким-то неведомым принципам. одним словом сплошной мейджик. как с этим жить - хз.

Deleted
()

Ы?

#include <stdint.h>
#include <stdlib.h>
struct Test {
  uint8_t a:3;
  uint8_t b:6;
  uint32_t c:13;
  uint32_t d:9;
};

int main(void) {
  printf("%d\n", sizeof(struct Test));
}

$ ./a.out 
8

А вообще сделай так:

import ctypes
class header(ctypes.Structure):
import ctypes
class header(ctypes.Structure):
  # _pack_ = 1
  _fields_ = [
    ('filedA', ctypes.c_uint32, 3),
    ('fieldB', ctypes.c_uint32, 6),
    ('fieldC', ctypes.c_uint32, 13),
    ('fieldD', ctypes.c_uint32, 9)
  ]

aa = header()
print(ctypes.sizeof(aa))
true_admin ★★★★★
()
Ответ на: комментарий от true_admin

а теперь добавь в эту шаткую конструкцию

('fieldE', ctypes.c_uint32, 2)

сломалось? :)

вот лучше скажи, почему с этим выравниванием так намудрили? почему не сделали просто бит к биту стыковку этих битфилдов с последующим выравниванием со стороны хвоста до нужного размера? нафига они каждое поле выравнивают? упростить доступ к полю? но ради чего, выиграть несколько тактов процессорного времени, но в замен обрести кучу гемора?

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

Давай напишем свой яп, со преферансом и стюардессами. Я вот только всё никак не придумаю синтаксиса «нормального». Каша в голове :(

true_admin ★★★★★
()

Если так чешется, что мешает собрать нужное 4х байтовое число через побитовый сдвиг и маски? Причем здесь struct вообще?;-)

На питоне можно написать класс с соотв полями и методом write (или pack).

AIv ★★★★★
()
Ответ на: комментарий от namezys

хотя бы потому, что на некоторых платформах доступ к невыравненным данным невозможен.

так почему бы для этих «некоторых» не выпилить алгоритм в отдельный кусок, как это делается для многих других частей компилятора при реализации поддержки какой-то специфичной платформы?

Deleted
()
Ответ на: комментарий от AIv

Если так чешется, что мешает собрать нужное 4х байтовое число через побитовый сдвиг и маски?

я в состоянии реализовать свой велосипед, но ведь это базовые механизмы и хочется их видеть из коробки.

Причем здесь struct вообще?

про pack я знаю, но работа со структурой дает бенефиты в производительности ибо сие интерпретируется как кусок памяти. с pack'ом мне нужно будет «парсить» и упаковывать каждый кусочек. не причем? :))). А если хидер протокола чуть менее чем весь из таких «неровностей» и с динамическим набором полей? Все еще не причем? )))

Вот то ли дело в ерланге реализована работа с битфилдами, просто сказка.

Deleted
()
Ответ на: комментарий от Deleted

вот лучше скажи, почему с этим выравниванием так намудрили?

Чтобы ты им не пользовался. Нет, серьезно - в Си «не используйте битовые поля, если вы не вынуждены это делать» стало уже общим местом.

сломалось? :)

У тебя получилось 33 бита, чего ты ждал?

про pack я знаю, но работа со структурой дает бенефиты в производительности ибо сие интерпретируется как кусок памяти

Ты мерял? А то звучит как-то сомнительно.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от Deleted

при реализации

вот оно ключевое слово. Многие вещи должны описываться стандартом, а не реализацией

namezys ★★★★
()
Ответ на: комментарий от Deleted

но ведь это базовые механизмы и хочется их видеть из коробки.

Да ладно. Битовые операции так часто нужны? Штука вообще не быстрая, если че

namezys ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.