Packing a ctypes struct containing bitfields.

K

Karthik

Hello Everybody,

I'm trying to create a packed structure in ctypes (with one 64-bit
element that is bitfielded to 48 bits),
unsuccessfully:

===================================
from ctypes import *

class foo (Structure):
_pack_ = 1
_fields_ = [
("bar", c_ulonglong, 48),
]

print("sizeof(foo) = %d" % sizeof(foo))
===================================
I'm expecting that this should print 6 - however, on my box, it prints
8.

The following piece of C code, when compiled and run, prints 6, which
is correct.
===================================
struct foo {
unsigned long long bar: 48;
};

printf("sizeof(foo) = %d", sizeof(foo));
===================================

So... what am I doing wrong?

Thanks,
Karthik.
 
K

Karthik

Karthik said:
 Hello Everybody,
 I'm trying to create a packed structure in ctypes (with one 64-bit
 element that is bitfielded to 48 bits),
 unsuccessfully:
===================================
 from ctypes import *
 class foo (Structure):
     _pack_ = 1
     _fields_ = [
         ("bar",    c_ulonglong, 48),
     ]
 print("sizeof(foo) = %d" % sizeof(foo))
===================================
 I'm expecting that this should print 6 - however, on my box, it prints
 8.
 The following piece of C code, when compiled and run, prints 6, which
 is correct.
===================================
 struct foo {
     unsigned long long bar: 48;
 };
 printf("sizeof(foo) = %d", sizeof(foo));
===================================
 So... what am I doing wrong?

I compiled and ran the above with gcc on my linux box - it prints 8
unless I add __attribute__((__packed__)) to the struct.

I'm not sure that using bitfields like that is a portable at all
between compilers let alone architectures.

I'd probably do

from ctypes import *

class foo (Structure):
    _pack_ = 1
    _fields_ = [
        ("bar0",    c_uint32),
        ("bar1",    c_uint16),
    ]
    def set_bar(self, bar):
        self.bar0 = bar & 0xFFFFFFFF
        self.bar1 = (bar >> 32) & 0xFFFF
    def get_bar(self):
        return (self.bar1 << 32) + self.bar0
    bar = property(get_bar, set_bar)

print "sizeof(foo) = %d" % sizeof(foo)
f = foo()
print f.bar
f.bar = 123456789012345
print f.bar

Which prints

sizeof(foo) = 6
0
123456789012345

Oops, sorry about the missing __attribute__((packed)) - that was an
error of
omission.

Thank you, Nick :)

I'm looking at some C code that's using bitfields in structs, and I'm
writing
python code that "imports" these structs and messes around with them -
unfortunately,
I'm not at liberty to change the C code to not use bitfields.

Your solution works fine, so that's what I'm going to use.

Thanks,
Karthik.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top