ctypes.c_void_p(-1) might not be C return (void *) -1

Thomas Heller theller at python.net
Thu Sep 28 14:41:10 EDT 2006


p.lavarre at ieee.org schrieb:
>> Subject: Python CTypes translation of (pv != NULL)

I've started a wiki page where I already added an entry about the above question.
Do you think the entry would have answered your question?

http://starship.python.net/crew/theller/moin.cgi/CodeSnippets

(My wiki should really be upgraded to a newer moinmoin version, however
it might be better to use another wiki for ctypes, maybe the python.org one, for this
stuff.)

> And so then the next related Faq is:
> 
> Q: How should I test for ((void *) -1)?
> 
> A:
> 
> (pv == 0xffffFFFF) works often.
> 
> (ctypes.cast(pv, ctypes.c_void_p).value == 0xffffFFFF) works better.
> 
> ((void *) -1) appears often in 32-bit Windows, behind the name
> INVALID_HANDLE_VALUE of the type HANDLE that is def'ed as the type
> PVOID that is def'ed as (void *).  -1 is xffffFFFF in 32-bit two's
> complement.
> 
> The more complex comparison works more often because specifying a
> restype doesn't decide the __class__ of the result.

True, in principle.  For me, on Windows, c_void_p(-1).value is the same
as c_void_p(0xFFFFFFFF).value, but it is -1 not 0xFFFFFFFF.

Worse, on 64-bit systems c_void_p(-1).value is 184467440737009661615, which
is the same as 0xFFFFFFFFFFFFFFFF.

So, to be portable, INVALID_HANDLE_VALUE should be defined like this:

INVALID_HANDLE_VALUE = c_void_p(-1).value

and your test would become

(ctypes.cast(pv, ctypes.c_void_p).value == INVALID_HANDLE_VALUE

Thomas

PS: It is inconsistent that the .value of a c_void_p instance is signed on
32-bit systems, and unsigned on 64-bit systems, but it seems we have to live
with that.  Fortunately, the c_void_p constructor accepts both signed and unsigned
Python ints and longs, so it should be possible to work around that fact.




More information about the Python-list mailing list