A: We are of course supposed to write something like:
def c_not_null(pv):
return (ctypes.cast(pv, ctypes.c_void_p).value != None)
Yes?
Working from the doc, me the clueless newbie, I was slow to guess such
relevant truths as:
ctypes.c_void_p(0).value == None
ctypes.c_void_p(0) != ctypes.c_void_p(0)
Curiously yours, thanks in advance, Pat LaVarre
>Q: The C idea of (pv != NULL) is said most directly in Python ctypes
>how?
Perhaps reading the ctypes tutorial? (both in the 2.5 docs and in
<http://starship.python.net/crew/theller/ctypes/tutorial.html>)
Gabriel Genellina
Softlab SRL
__________________________________________________
Preguntá. Respondé. Descubrí.
Todo lo que querías saber, y lo que ni imaginabas,
está en Yahoo! Respuestas (Beta).
¡Probalo ya!
http://www.yahoo.com.ar/respuestas
Generally pointer instances have a False boolean value, so
'if pv: ....'
should work. Except for c_void_p, c_char_p and c_wchar_p instances.
Thomas
Actually, no. I see three answers or zero, depending on how you like
to count.
Yes that flat edition helps makes this clear, thank you - there I can
more easily grab an ordered list of all matches of text than in the
more prominent shadow:
http://docs.python.org/dev/lib/module-ctypes.html
I see direct discussion only of how to construct null pointers, no
discussion of how to test for them. Specifically:
The hint { bool(null_ptr) == False } could be read to mean try ==
False, in the "Pointers" text.
The hint { ("values", POINTER(c_int))] ... bar.values = None } could be
read to say try == None, in the "Calling functions" text.
The hint { if item.name is None } could be read to say try is None, in
the "Accessing values exported from dlls" text.
I'm such a Python newbie that I didn't know is None existed alongside
== None.
I guess I'll next dig into that along with the answer below from CTypes
author Thomas Heller.
Please can we give me an example of these exceptions?
Indeed those types are the _p types I use most often. Now here
'bool(pv)' and 'if pv' tell me that null is False and non-null is True,
for every kind of null or non-null that I know how to construct.
Is that mapping somehow not reliable across all instances? Or not
cross-platform?
You did mean to say that the Python fragments 'bool(pv)' and 'if pv'
somehow are not accurate translations of the C fragments 'pv != NULL'
and 'if pv'? Something other kind of Python is?
> > >Q: The C idea of (pv != NULL) is said most directly in Python ctypes
> > >how?
> >
> > Perhaps reading the ctypes tutorial? (both in the 2.5 docs and in
> > <http://starship.python.net/crew/theller/ctypes/tutorial.html>)
>
>Actually, no. I see three answers or zero, depending on how you like
>to count.
>
>Yes that flat edition helps makes this clear, thank you - there I can
>more easily grab an ordered list of all matches of text than in the
>more prominent shadow:
>http://docs.python.org/dev/lib/module-ctypes.html
>
>I see direct discussion only of how to construct null pointers, no
>discussion of how to test for them. Specifically:
>
>The hint { bool(null_ptr) == False } could be read to mean try ==
>False, in the "Pointers" text.
It says:
NULL pointers have a False boolean value:
>>> null_ptr = POINTER(c_int)()
>>> print bool(null_ptr)
False
That means that NULL pointers are considered False in a boolean
expression (and you could assume that non-NULL pointers are True, as
any other object in general), so you can test a NULL pointer with a
simple "if ptr: whatever"
--- cut ---
from ctypes import *
null_ptr = POINTER(c_int)()
x=c_int(1234)
other_ptr = pointer(x)
if null_ptr: print "null_ptr is not NULL"
else: print "null_ptr is NULL"
if other_ptr: print "other_ptr is not NULL"
else: print "other_ptr is NULL"
--- cut ---
It's really the same as bool([])==False, bool(any_non_empty_list)==True:
L = [1,2,3]
while L:
print L.pop()
You don't say:
while bool(L)==True:
(do you?)
CTypes nulls fetched from a struct feel more like None than do CTypes
nulls fetched from elsewhere, astonishing me the Python newbie, e.g.:
$ python nulls.py
True True True None None
True True True None None
True False False None c_char_p(None)
$
$ cat nulls.py
from ctypes import *
class struct_aa(Structure):
_fields_ = [("chars", c_char_p)]
pv = None
print not pv, pv == None, pv is None, cast(pv, c_void_p).value, pv
pv = struct_aa().chars
print not pv, pv == None, pv is None, cast(pv, c_void_p).value, pv
pv = cast(c_void_p(0), c_char_p)
print not pv, pv == None, pv is None, cast(pv, c_void_p).value, pv
$
Possibly relevant, though grabbed at random, is:
/// PEP 8 -- Style Guide for Python Code
/// http://www.python.org/dev/peps/pep-0008/
... beware of writing "if x" when you really mean "if x is not None" --
e.g. when testing whether a variable or argument that defaults to None
was set to some other value. The other value might have a type (such
as a container) that could be false in a boolean context!
///
Yes.
> That means that NULL pointers are considered False in a boolean
> expression (and you could assume that non-NULL pointers are True, as
> any other object in general),
I see this now that you show the clueless newbie me, yes thank you.
Except now by showing me here we have provoked the authority Thomas
Heller to say:
> > > Generally pointer instances have a False boolean value, so
> > > 'if pv: ....'
> > > should work. Except for c_void_p, c_char_p and c_wchar_p instances.
That English I do not understand. "Except" how?
> so you can test a NULL pointer with a
> simple "if ptr: whatever"
Apparently, yes, except for the "except" above.
> --- cut ---
> from ctypes import *
> null_ptr = POINTER(c_int)()
> x=c_int(1234)
> other_ptr = pointer(x)
>
> if null_ptr: print "null_ptr is not NULL"
> else: print "null_ptr is NULL"
>
> if other_ptr: print "other_ptr is not NULL"
> else: print "other_ptr is NULL"
> --- cut ---
Yes.
> It's really the same as bool([])==False, bool(any_non_empty_list)==True:
>
> L = [1,2,3]
> while L:
> print L.pop()
>
> You don't say:
> while bool(L)==True:
>
> (do you?)
Oh that's exactly how my newbie innocence led me astray.
Rather than working first to translate the C 'if pv', I worked first to
translate the C '(pv != NULL)', and then I got lost (and as yet still
am lost) in newbie astonishment over some nulls feeling more like None
than others.
Actually I was wrong - there is no exception. To summarize:
All ctypes NULL pointers have a False boolean value.
So, this C-code:
if (pv) { /* or 'if (pv != NULL)' */
return *pv; /* whatever */
} else {
/* handle NULL pointer */
}
translates to this Python code:
if pv:
return pv[0] # or whatever
else:
# pv is a NULL pointer
Works for instances of c_char_p, c_void_p, c_wchar_p,
and instances of POINTER(some_ctype).
If you want to make the 'if pv:' line more verbose, you could as well
write 'if bool(pv):' or 'if bool(pv) == False', but why would
you want to do this?
Thomas
> > That means that NULL pointers are considered False in a boolean
> > expression (and you could assume that non-NULL pointers are True, as
> > any other object in general),
>
>I see this now that you show the clueless newbie me, yes thank you.
>Except now by showing me here we have provoked the authority Thomas
>Heller to say:
>
> > > > Generally pointer instances have a False boolean value, so
> > > > 'if pv: ....'
> > > > should work. Except for c_void_p, c_char_p and c_wchar_p instances.
>
>That English I do not understand. "Except" how?
Uh? That's wrong. Where did you find that? Should read "Generally
NULL pointer instances have..."
In short, whenever you see, in C:
if (ptr1) { whatever }
if (ptr2 != NULL) { whatever }
if (ptr3 == NULL) { whatever }
that goes into python:
if ptr1: ...
if ptr2: ...
if not ptr3: ...
>Oh that's exactly how my newbie innocence led me astray.
Don't apologize, it's not easy to learn Python *and* learn to link an
external library at the same time...
> > > http://starship.python.net/crew/theller/ctypes/tutorial.html
> > ...
> > direct discussion only of how to construct null pointers,
> > no discussion of how to test for them ...
> > ...
> > could be read to mean try ... == ... is ... False ... None ...
>
>CTypes nulls fetched from a struct feel more like None than do CTypes
>nulls fetched from elsewhere, astonishing me the Python newbie, e.g.:
No, the difference comes from the kind of pointer type, char* gets
converted to string or None. See the table on section 14.14.1.4
Fundamental data types
>$ python nulls.py
>True True True None None
>True True True None None
>True False False None c_char_p(None)
>$
>$ cat nulls.py
>from ctypes import *
>class struct_aa(Structure):
> _fields_ = [("chars", c_char_p)]
>pv = None
>print not pv, pv == None, pv is None, cast(pv, c_void_p).value, pv
>pv = struct_aa().chars
>print not pv, pv == None, pv is None, cast(pv, c_void_p).value, pv
>pv = cast(c_void_p(0), c_char_p)
>print not pv, pv == None, pv is None, cast(pv, c_void_p).value, pv
>$
c_char_p is *not* a pointer in Python, since Python does not have pointers.
Either the original C pointer was NULL: then the Python value is None
Or the original C pointer was not NULL: then the Python value is a string
>Possibly relevant, though grabbed at random, is:
>
>/// PEP 8 -- Style Guide for Python Code
>/// http://www.python.org/dev/peps/pep-0008/
>
>... beware of writing "if x" when you really mean "if x is not None" --
>e.g. when testing whether a variable or argument that defaults to None
>was set to some other value. The other value might have a type (such
>as a container) that could be false in a boolean context!
This is exactly the case: None is *not* a pointer (neither any other
kind of ctypes object), it's an object -a singleton, i.e., there
exist exactly a single one instance of None).
If you want to check if some kind of pointer is NULL or not, do *not*
check if it is None or not, check its Boolean value, again:
if ptr: xxx
if not ptr: xxx
Quoted in full from the gift:
Subject: Re: Python CTypes translation of (pv != NULL)
Date: Tue, 26 Sep 2006 11:48:52 +0200
Message-ID: <mailman.654.11592641...@python.org>
http://groups.google.com/group/comp.lang.python/msg/f9f13e731ea3cad7
Cached and pondered just slightly before the gift of a complete
disavowal came after:
Subject: Re: Python CTypes translation of (pv != NULL)
Date: Wed, 27 Sep 2006 20:22:47 +0200
Message-ID: <mailman.823.11593814...@python.org>
http://groups.google.com/group/comp.lang.python/msg/6584d964a70b7a2d
/// Copied 2006-09-28 from
/// http://starship.python.net/crew/theller/moin.cgi/CodeSnippets
1.2 Check for NULL ctypes pointers
The truth value of any NULL ctypes pointer instance is False.
So, this C code
if (pv == NULL)
/* handle NULL pointer */
else
/* handle non-NULL pointer */
translates to this Python code
if not pv:
# handle NULL pointer
else:
# handle non-NULL pointer
The above is true for instances of c_void_p, c_char_p, c_wchar_p, and
POINTER(some_ctype).
///