[Tutor] working with c_byte?

Dave Angel d at davea.name
Sat Mar 24 05:37:46 CET 2012


On 03/23/2012 11:51 PM, Alex Hall wrote:
> Hi all,
> I am trying to read battery information. I found an example that sets
> up a ctypes structure to get the information from a kernel call, and
> it works... except that I just realized the values of some fields are
> added. For instance, a value of 1 means that the battery is "high",
> and 8 means it is charging. I didn't realize until just now that
> Windows will give both of these to me as 9, so the dict I set up to
> see what the value is won't work. Similarly, a value of 255 is always
> seen in Python as -128, even if I multiply it by -1 to flip it.

Don't multiply by -1, simply convert to an int, and use modulo 256 to 
get it to a positive value.
     newval = int(cbyte) % 256

Or perhaps use c_ubyte instead of c_byte to get unsigned values in the 
first place.

A signed value uses the highest bit to indicate a negative value.  For 
an 8 bit signed value, the values range from -128 to 127.  There is no 
positive value above 127, so multiplying by -1 is the wrong answer.  
Besides if there are other bits in the byte, they'll get changed as 
well.  The modulo trick won't affect any of the 8 bits, only their 
interpretation.

>   The
> value I'm working with is a ctypes.c_byte. Here is the data structure:
> class SYSTEM_POWER_STATUS(ctypes.Structure):
>   _fields_=[
>    ("ACLineStatus", ctypes.c_byte),
>    ("BatteryFlag", ctypes.c_byte),
>    ("BatteryLifePercent", ctypes.c_byte),
>    ("Reserved1", ctypes.c_byte),
>    ("BatteryLifeTime", ctypes.wintypes.DWORD),
>    ("BatteryFullLiveTime", ctypes.wintypes.DWORD)
>   ]
>
> and here is my dict to use when looking up the meaning of the BatteryFlag:
> status_constants = {
>   1:"high",
>   2:"low",
>   4:"critical",
>   8:"charging",
>   128:"no system battery",
>   -128:"no system battery", #hack to get around odd negation of 128
> flag... how to fix?
>   255:"unknown"
> }
>

cbyte & 1   will be nonzero (1) if that one "high" flag is set, 
regardless of the others.
cbyte & 2    will be nonzero (2) if  "low", and so on.

for flag in 1,2,4,8,16,32,64,128:
       if cbyte & flag:
              print  status_constants[cbyte & flag]


> Of course, 9 means the battery is high and charging, but how do I
> interpret an arbitrary integer as the sum of its flags? Is there a
> binary trick I can use? I could record all the 1s in the binary number
> and look up their positions... but is there a simpler way? If I do
> that, where is the sign bit in c_byte? TIA.
>
>

As I said earlier, the sign bit is 128, the highest bit in the byte.  
The number is 2's complement, which is why you must use modulo to 
convert it, not multiplication by -1.  The latter approach would work if 
the machine used ones complement.

-- 

DaveA



More information about the Tutor mailing list