Issue #19023: Document ctypes array and pointer classes
Also add some more tests. Based on patch by Sye van der Veen.
This commit is contained in:
parent
4b40c3e69e
commit
a339e86dc0
|
@ -708,8 +708,8 @@ Pointer instances are created by calling the :func:`pointer` function on a
|
|||
>>> pi = pointer(i)
|
||||
>>>
|
||||
|
||||
Pointer instances have a :attr:`contents` attribute which returns the object to
|
||||
which the pointer points, the ``i`` object above::
|
||||
Pointer instances have a :attr:`~_Pointer.contents` attribute which
|
||||
returns the object to which the pointer points, the ``i`` object above::
|
||||
|
||||
>>> pi.contents
|
||||
c_long(42)
|
||||
|
@ -2512,6 +2512,56 @@ other data types containing pointer type fields.
|
|||
Arrays and pointers
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Not yet written - please see the sections :ref:`ctypes-pointers` and section
|
||||
:ref:`ctypes-arrays` in the tutorial.
|
||||
.. class:: Array(\*args)
|
||||
|
||||
Abstract base class for arrays.
|
||||
|
||||
The recommended way to create concrete array types is by multiplying any
|
||||
:mod:`ctypes` data type with a positive integer. Alternatively, you can subclass
|
||||
this type and define :attr:`_length_` and :attr:`_type_` class variables.
|
||||
Array elements can be read and written using standard
|
||||
subscript and slice accesses; for slice reads, the resulting object is
|
||||
*not* itself an :class:`Array`.
|
||||
|
||||
|
||||
.. attribute:: _length_
|
||||
|
||||
A positive integer specifying the number of elements in the array.
|
||||
Out-of-range subscripts result in an :exc:`IndexError`. Will be
|
||||
returned by :func:`len`.
|
||||
|
||||
|
||||
.. attribute:: _type_
|
||||
|
||||
Specifies the type of each element in the array.
|
||||
|
||||
|
||||
Array subclass constructors accept positional arguments, used to
|
||||
initialize the elements in order.
|
||||
|
||||
|
||||
.. class:: _Pointer
|
||||
|
||||
Private, abstract base class for pointers.
|
||||
|
||||
Concrete pointer types are created by calling :func:`POINTER` with the
|
||||
type that will be pointed to; this is done automatically by
|
||||
:func:`pointer`.
|
||||
|
||||
If a pointer points to an array, its elements can be read and
|
||||
written using standard subscript and slice accesses. Pointer objects
|
||||
have no size, so :func:`len` will raise :exc:`TypeError`. Negative
|
||||
subscripts will read from the memory *before* the pointer (as in C), and
|
||||
out-of-range subscripts will probably crash with an access violation (if
|
||||
you're lucky).
|
||||
|
||||
|
||||
.. attribute:: _type_
|
||||
|
||||
Specifies the type pointed to.
|
||||
|
||||
.. attribute:: contents
|
||||
|
||||
Returns the object to which to pointer points. Assigning to this
|
||||
attribute changes the pointer to point to the assigned object.
|
||||
|
||||
|
|
|
@ -24,20 +24,24 @@ class ArrayTestCase(unittest.TestCase):
|
|||
self.assertEqual(len(ia), alen)
|
||||
|
||||
# slot values ok?
|
||||
values = [ia[i] for i in range(len(init))]
|
||||
values = [ia[i] for i in range(alen)]
|
||||
self.assertEqual(values, init)
|
||||
|
||||
# out-of-bounds accesses should be caught
|
||||
with self.assertRaises(IndexError): ia[alen]
|
||||
with self.assertRaises(IndexError): ia[-alen-1]
|
||||
|
||||
# change the items
|
||||
from operator import setitem
|
||||
new_values = range(42, 42+alen)
|
||||
[setitem(ia, n, new_values[n]) for n in range(alen)]
|
||||
values = [ia[i] for i in range(len(init))]
|
||||
values = [ia[i] for i in range(alen)]
|
||||
self.assertEqual(values, new_values)
|
||||
|
||||
# are the items initialized to 0?
|
||||
ia = int_array()
|
||||
values = [ia[i] for i in range(len(init))]
|
||||
self.assertEqual(values, [0] * len(init))
|
||||
values = [ia[i] for i in range(alen)]
|
||||
self.assertEqual(values, [0] * alen)
|
||||
|
||||
# Too many initializers should be caught
|
||||
self.assertRaises(IndexError, int_array, *range(alen*2))
|
||||
|
|
|
@ -53,9 +53,13 @@ class PointersTestCase(unittest.TestCase):
|
|||
# C code:
|
||||
# int x = 12321;
|
||||
# res = &x
|
||||
res.contents = c_int(12321)
|
||||
x = c_int(12321)
|
||||
res.contents = x
|
||||
self.assertEqual(i.value, 54345)
|
||||
|
||||
x.value = -99
|
||||
self.assertEqual(res.contents.value, -99)
|
||||
|
||||
def test_callbacks_with_pointers(self):
|
||||
# a function type receiving a pointer
|
||||
PROTOTYPE = CFUNCTYPE(c_int, POINTER(c_int))
|
||||
|
@ -128,9 +132,10 @@ class PointersTestCase(unittest.TestCase):
|
|||
|
||||
def test_basic(self):
|
||||
p = pointer(c_int(42))
|
||||
# Although a pointer can be indexed, it ha no length
|
||||
# Although a pointer can be indexed, it has no length
|
||||
self.assertRaises(TypeError, len, p)
|
||||
self.assertEqual(p[0], 42)
|
||||
self.assertEqual(p[0:1], [42])
|
||||
self.assertEqual(p.contents.value, 42)
|
||||
|
||||
def test_charpp(self):
|
||||
|
|
Loading…
Reference in New Issue