eryk sun at 2018/4/14 PM 05:27 wrote:
On Fri, Apr 13, 2018 at 8:44 AM, Jach Fong <> wrote:

After studying the example you explained in your previous post replied to
Gregory Ewing, I had noticed that until today I was totally misunderstand
the meaning of the c_char_p. I always think it "is" a pointer, but actually
it's just a ctypes type, maybe literarily looks like a C pointer, but not a
pointer from the ctypes view at all:-)

Here's a list of type classes in ctypes:

     class             metaclass
     _SimpleCData      PyCSimpleType
     _Pointer          PyCPointerType
     _CFuncPtr         PyCFuncPtrType
     Array             PyCArrayType
     Structure         PyCStructType
     Union             UnionType

These classes share a common _CData base class. Note that the _ctypes
extension module doesn't directly expose _CData, nor any of the

ctypes type checking primarily uses Python type checking, so we
generally do not subclass these types directly, except for Structure
and Union. Instead we have a set of predefined simple types that
subclass _SimpleCData (e.g. c_int, c_char), and we use factory
functions to create pointer types (e.g. POINTER, CFUNCTYPE), which
cache the created type. For arrays, we rely on the base _CData
sequence-repeat functionality (e.g. c_int * 3), which also caches the
Array subclass that it creates.

Type caching ensures that two expressions that create an equivalent C
type return the same class. For example, if you have `c_char * 3` in
two places, it should be the same type:

     >>> cls = ctypes.c_char * 3
     >>> (ctypes.c_char * 3) is cls
Thanks for your description. To digest it, I may need to dive into its source jungle:-(

The simple types c_void_p, c_char_p, and c_wchar_p are pointers.
However, since they subclass _SimpleCData instead of _Pointer, they
inherit the behavior of simple types.

The ctypes document says:
"Pointer instances have a contents attribute which returns the object to which the pointer points"

>>> buf0 = ctypes.create_string_buffer(b'spam')

>>> pvoid = ctypes.c_void_p(ctypes.addressof(buf0))
>>> pvoid.contents
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'c_void_p' object has no attribute 'contents'
>>> pvoid.value

>>> pp = ctypes.pointer(buf0)
>>> pp.contents
<ctypes.c_char_Array_5 object at 0x021C8F30>
>>> pp.value
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'LP_c_char_Array_5' object has no attribute 'value'

It looks like the c_void_p is not of a pointer type:-)


In particular they have get/set
functions that implicitly convert to and from native Python types when
they're used in aggregate types (arrays, structs, unions), when
indexing or slicing a _Pointer instance, or as the result or argument
of a function pointer (i.e. _CFuncPtr subclass).

This email has been checked for viruses by Avast antivirus software.


Reply via email to