0

I want to pack a 10-bit integer and a 54-bit integer into a 64-bit structure. But this code ends up using 128 bits.

from ctypes import *

class ABC(Structure):
    _fields_ = [("a", c_int, 10), ("b", c_uint64, 54)]

print(sizeof(ABC) * 8) # 128
2
  • Do you consider only unsigned integers? Commented Oct 4, 2015 at 17:23
  • No, signed and unsigned. But if you have a solution for unsigned only, I would like to see it. Commented Oct 4, 2015 at 17:25

2 Answers 2

3

For whatever reason, ctypes doesn't do bit packing properly when you mix different width objects into the same byte. Something like this appears to work for me:

class ABC(Structure):
   _pack_ = 1
   _fields_ = [("a",c_int64,10),("b",c_uint64,54)]
Sign up to request clarification or add additional context in comments.

4 Comments

What exactly does the _pack_ attribute do and what are valid values for it?
stackoverflow.com/questions/14771150/… - in essence it emulates C's pragma pack, but since your structure is byte aligned to a standard width already it probably affects nothing here
As for valid values, docs.python.org/2/library/ctypes.html#ctypes.Structure._pack_ and other comments while searching around indicate that it'll take small positive powers of 2
I think this would apply to Python. msdn.microsoft.com/en-us/library/2e70t5y1.aspx Specifies the value, in bytes, to be used for packing. ... Valid values are 1, 2, 4, 8, and 16. The alignment of a member will be on a boundary that is either a multiple of n or a multiple of the size of the member, whichever is smaller.
1

Considering int_10 and int_54 are integers with desired bitness:

>>> def pack(int_10, int_54):
...     return (int_10 & 0x3FF) | (int_54 & 0x3FFFFFFFFFFFFF) << 10

>>> bin(pack(1, 1))
'0b10000000001'
>>> bin(pack(1, 2 ** 54 - 1))
'0b1111111111111111111111111111111111111111111111111111110000000001'
>>> bin(pack(2 ** 10, 2 ** 54))
'0b0'

You can then pack the resulting integer using struct.pack to get a byte string.

>>> import struct
>>> struct.pack('Q', pack(2 ** 10 - 1, 2 ** 54 - 1))
'\xff\xff\xff\xff\xff\xff\xff\xff'

1 Comment

This is ok for compacting data for storage and such. But it won't let me manipulate the bit fields easily, like: x=ABC(10,20);x.a=-15;x.b=50 I am really looking for Python's built-in functionality, if it exists.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.