[pypy-svn] r50962 - in pypy/dist/pypy/lib: _ctypes app_test/ctypes

fijal at codespeak.net fijal at codespeak.net
Thu Jan 24 14:20:36 CET 2008


Author: fijal
Date: Thu Jan 24 14:20:36 2008
New Revision: 50962

Added:
   pypy/dist/pypy/lib/app_test/ctypes/test_array_in_pointer.py   (contents, props changed)
Modified:
   pypy/dist/pypy/lib/_ctypes/array.py
   pypy/dist/pypy/lib/_ctypes/pointer.py
   pypy/dist/pypy/lib/_ctypes/structure.py
   pypy/dist/pypy/lib/app_test/ctypes/test_memfunctions.py
Log:
A bit of special-logic and 3 more tests pass.


Modified: pypy/dist/pypy/lib/_ctypes/array.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/array.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/array.py	Thu Jan 24 14:20:36 2008
@@ -53,6 +53,25 @@
             return self(*value)
         return _CDataMeta.from_param(self, value)
 
+def array_get_slice_params(self, index):
+    if index.step is not None:
+        raise TypeError("3 arg slices not supported (for no reason)")
+    start = index.start or 0
+    stop = index.stop or self._length_
+    return start, stop
+
+def array_slice_setitem(self, index, value):
+    start, stop = self._get_slice_params(index)
+    for i in range(start, stop):
+        self[i] = value[i - start]
+
+def array_slice_getitem(self, index):
+    start, stop = self._get_slice_params(index)
+    l = [self[i] for i in range(start, stop)]
+    if getattr(self._type_, '_type_', None) == 'c':
+        return "".join(l)
+    return l
+
 class Array(_CData):
     __metaclass__ = ArrayMeta
     _ffiletter = 'P'
@@ -70,24 +89,9 @@
         else:
             raise IndexError
 
-    def _get_slice_params(self, index):
-        if index.step is not None:
-            raise TypeError("3 arg slices not supported (for no reason)")
-        start = index.start or 0
-        stop = index.stop or self._length_
-        return start, stop
-    
-    def _slice_setitem(self, index, value):
-        start, stop = self._get_slice_params(index)
-        for i in range(start, stop):
-            self[i] = value[i - start]
-
-    def _slice_getitem(self, index):
-        start, stop = self._get_slice_params(index)
-        l = [self[i] for i in range(start, stop)]
-        if getattr(self._type_, '_type_', None) == 'c':
-            return "".join(l)
-        return l
+    _get_slice_params = array_get_slice_params
+    _slice_getitem = array_slice_getitem
+    _slice_setitem = array_slice_setitem
 
     def _subarray(self, index):
         """Return a _rawffi array of length 1 whose address is the same as

Modified: pypy/dist/pypy/lib/_ctypes/pointer.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/pointer.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/pointer.py	Thu Jan 24 14:20:36 2008
@@ -2,7 +2,8 @@
 import _rawffi
 from _ctypes.basics import _CData, _CDataMeta, cdata_from_address
 from _ctypes.basics import sizeof, byref
-from _ctypes.array import Array
+from _ctypes.array import Array, array_get_slice_params, array_slice_getitem,\
+     array_slice_setitem
 
 DEFAULT_VALUE = object()
 
@@ -78,14 +79,19 @@
         value = value._buffer
         self._buffer[0] = value
 
+    _get_slice_params = array_get_slice_params
+    _slice_getitem = array_slice_getitem
+
     def _subarray(self, index=0):
         """Return a _rawffi array of length 1 whose address is the same as
         the index'th item to which self is pointing."""
         address = self._buffer[0]
         address += index * sizeof(self._type_)
-        return self._type_._ffiarray.fromaddress(address, 1)
+        return self._type_.from_address(address)._buffer
 
     def __getitem__(self, index):
+        if isinstance(index, slice):
+            return self._slice_getitem(index)
         return self._type_._CData_output(self._subarray(index))
 
     def __setitem__(self, index, value):
@@ -100,12 +106,17 @@
 
 
 def _cast_addr(obj, _, tp):
-    if not (isinstance(obj, _CData) and type(obj)._is_pointer_like()):
-        raise TypeError("cast() argument 1 must be a pointer, not %s"
-                        % (type(obj),))
     if not (isinstance(tp, _CDataMeta) and tp._is_pointer_like()):
         raise TypeError("cast() argument 2 must be a pointer type, not %s"
                         % (tp,))
+    if isinstance(obj, Array):
+        ptr = tp.__new__(tp)
+        ptr._buffer = tp._ffiarray(1)
+        ptr._buffer[0] = obj._buffer
+        return ptr
+    if not (isinstance(obj, _CData) and type(obj)._is_pointer_like()):
+        raise TypeError("cast() argument 1 must be a pointer, not %s"
+                        % (type(obj),))
     result = tp()
     result._buffer[0] = obj._buffer[0]
     return result

Modified: pypy/dist/pypy/lib/_ctypes/structure.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/structure.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/structure.py	Thu Jan 24 14:20:36 2008
@@ -117,7 +117,6 @@
         return self._ffistruct.alignment
 
     def _CData_output(self, resarray):
-        assert isinstance(resarray, _rawffi.ArrayInstance)
         res = self.__new__(self)
         ffistruct = self._ffistruct.fromaddress(resarray.buffer)
         res.__dict__['_buffer'] = ffistruct

Added: pypy/dist/pypy/lib/app_test/ctypes/test_array_in_pointer.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lib/app_test/ctypes/test_array_in_pointer.py	Thu Jan 24 14:20:36 2008
@@ -0,0 +1,63 @@
+from ctypes import *
+from binascii import hexlify
+import re
+import _rawffi
+
+def dump(obj):
+    # helper function to dump memory contents in hex, with a hyphen
+    # between the bytes.
+    # cast it to the raw buffer
+    size = sizeof(obj)
+    a = _rawffi.Array('c').fromaddress(obj._buffer.buffer, size)
+    h = hexlify([a[i] for i in range(len(a))])
+    return re.sub(r"(..)", r"\1-", h)[:-1]
+
+class Value(Structure):
+    _fields_ = [("val", c_byte)]
+
+class Container(Structure):
+    _fields_ = [("pvalues", POINTER(Value))]
+
+class TestOne:
+    def test(self):
+        # create an array of 4 values
+        val_array = (Value * 4)()
+
+        # create a container, which holds a pointer to the pvalues array.
+        c = Container()
+        c.pvalues = val_array
+
+        # memory contains 4 NUL bytes now, that's correct
+        assert "00-00-00-00" == dump(val_array)
+
+        # set the values of the array through the pointer:
+        for i in range(4):
+            c.pvalues[i].val = i + 1
+
+        values = [c.pvalues[i].val for i in range(4)]
+
+        # These are the expected results: here s the bug!
+        assert (
+            (values, dump(val_array))) == (
+            ([1, 2, 3, 4], "01-02-03-04")
+        )
+
+    def test_2(self):
+
+        val_array = (Value * 4)()
+
+        # memory contains 4 NUL bytes now, that's correct
+        assert "00-00-00-00" == dump(val_array)
+
+        ptr = cast(val_array, POINTER(Value))
+        # set the values of the array through the pointer:
+        for i in range(4):
+            ptr[i].val = i + 1
+
+        values = [ptr[i].val for i in range(4)]
+
+        # These are the expected results: here s the bug!
+        assert (
+            (values, dump(val_array))) == (
+            ([1, 2, 3, 4], "01-02-03-04")
+        )

Modified: pypy/dist/pypy/lib/app_test/ctypes/test_memfunctions.py
==============================================================================
--- pypy/dist/pypy/lib/app_test/ctypes/test_memfunctions.py	(original)
+++ pypy/dist/pypy/lib/app_test/ctypes/test_memfunctions.py	Thu Jan 24 14:20:36 2008
@@ -27,7 +27,6 @@
         assert string_at(a, 20) == "xxxxxxxxxxxxxxxx\0\0\0\0"
 
     def test_cast(self):
-        py.test.skip("I'm not sure I understood")
         a = (c_ubyte * 32)(*map(ord, "abcdef"))
         assert cast(a, c_char_p).value == "abcdef"
         assert cast(a, POINTER(c_byte))[:7] == (



More information about the Pypy-commit mailing list