[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