Reputation: 397
I'm trying to make an 11-bit ID field for a CAN communication channel. I think I should be able to use:
import ctypes
class ID(ctypes.Union):
_fields_ = [('device', ctypes.c_int, 3), # 3 bits for device id
('message', ctypes.c_int, 8)] # 8 bits for message ID
The issue is what happens when I try to validate that an instance of this class is what I wanted. Specifically:
>>> x = ID()
>>> type(x.device)
<type 'int'>
Why is that an int and not a c_int? Likewise:
>>> x = ID()
>>> x.device.bit_length()
0
which is precisely what I didn't want.
EDIT:
Thanks for the help! I should definitely be using a struct.
I'm trying to make an object that represents the identifier and data sections of a CAN data frame. The convention I'm working with further divides the identifier frame into 3- and 8-bit segments, representing the device and message ID, respectively. what I'd like is a class representing the identifier frame, in which I can assign values to members corresponding to my convention's device and message IDs, and which serializes into an 11-bit ID value.
Maybe I need to take another look at the C library I'm using for the CAN channel--it may be that I can use a 16-bit struct of which I only use 11 bits.
Upvotes: 1
Views: 478
Reputation: 365627
Inside the Union
, the device
member is stored using 8 bits.
However, ctypes
will automatically convert back and forth to native int
types for you, using (a good approximation of) the usual C rules for converting between types. For example, try this:
>>> x.device = 257
>>> x.device
1
So, you don't have anything to fix here.
However, you do have a problem:
I'm trying to make an 11-bit ID field for a CAN communication channel.
A Union
of an 8-bit int and a 3-bit int is 8 bits, just as in C. You want a Struct
. See Structures and unions and the type references linked from there for details.
On top of that, while a Struct
of a 3-bit int and an 8-bit int only has 11 bits of useful information, it will almost certainly take up at least 16 bits of memory, with 5 bits of padding.* You can only address memory a byte (8 bits) at a time. So… I'm not sure exactly what you were trying to do with this ID, but I suspect it's not going to work. If you explain your actual problem, ideally with some complete sample code, we can probably help.
* In fact, at least in current CPython versions, it will actually take up 32 bits of memory. See eryksun's comments for more details.
Upvotes: 2