]> granicus.if.org Git - python/commitdiff
Issue #19023: Document ctypes array and pointer classes
authorMartin Panter <vadmium+py@gmail.com>
Fri, 29 Jan 2016 10:12:19 +0000 (10:12 +0000)
committerMartin Panter <vadmium+py@gmail.com>
Fri, 29 Jan 2016 10:12:19 +0000 (10:12 +0000)
Also add some more tests. Based on patch by Sye van der Veen.

Doc/library/ctypes.rst
Lib/ctypes/test/test_arrays.py
Lib/ctypes/test/test_pointers.py
Misc/ACKS

index 99a2c4dd423746a96b34e983fb8d84a5f797de9a..386a44dfba7c2fcb79a9cff985c334de127c259d 100644 (file)
@@ -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.
 
index 47e95ee0fd781517f765a0e8e4c6be28edb48c39..49aaab52b93b49384a5de35849cfa071edd82ed6 100644 (file)
@@ -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))
index 6915cda2bd1e156f475f79b2f11d3a590060af9f..24b0546c89bf747f07f52d385038b3d9e46adcb1 100644 (file)
@@ -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):
index 2ceb0411d45b4e8d9a7f1707575a93bbb311b6ce..0a71085551f5f32408c94338c8ed8b76f7008ba2 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1418,6 +1418,7 @@ Dmitry Vasiliev
 Sebastian Ortiz Vasquez
 Alexandre Vassalotti
 Nadeem Vawda
+Sye van der Veen
 Frank Vercruesse
 Mike Verdone
 Jaap Vermeulen