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

fijal at codespeak.net fijal at codespeak.net
Fri Jan 25 20:26:32 CET 2008


Author: fijal
Date: Fri Jan 25 20:26:31 2008
New Revision: 51046

Added:
   pypy/dist/pypy/lib/app_test/ctypes/test_cast.py   (contents, props changed)
Modified:
   pypy/dist/pypy/lib/_ctypes/pointer.py
   pypy/dist/pypy/lib/_ctypes/primitive.py
Log:
* Casting from integers
* get/setvalue for c_wchar_p
* allow setitem on pointers on further indices (cpython allows that)


Modified: pypy/dist/pypy/lib/_ctypes/pointer.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/pointer.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/pointer.py	Fri Jan 25 20:26:31 2008
@@ -95,8 +95,6 @@
         return self._type_._CData_output(self._subarray(index))
 
     def __setitem__(self, index, value):
-        if index != 0:
-            raise IndexError
         self._subarray(index)[0] = self._type_._CData_input(value)[0]
 
     def __nonzero__(self):
@@ -114,6 +112,10 @@
         ptr._buffer = tp._ffiarray(1)
         ptr._buffer[0] = obj._buffer
         return ptr
+    if isinstance(obj, (int, long)):
+        result = tp()
+        result._buffer[0] = obj
+        return result
     if not (isinstance(obj, _CData) and type(obj)._is_pointer_like()):
         raise TypeError("cast() argument 1 must be a pointer, not %s"
                         % (type(obj),))

Modified: pypy/dist/pypy/lib/_ctypes/primitive.py
==============================================================================
--- pypy/dist/pypy/lib/_ctypes/primitive.py	(original)
+++ pypy/dist/pypy/lib/_ctypes/primitive.py	Fri Jan 25 20:26:31 2008
@@ -76,6 +76,25 @@
                     value = 0
                 self._buffer[0] = value
             result.value = property(_getvalue, _setvalue)
+        elif tp == 'Z':
+            # c_wchar_p
+            from _ctypes import Array, _Pointer, _wstring_at_addr
+            def _getvalue(self):
+                addr = self._buffer[0]
+                if addr == 0:
+                    return None
+                else:
+                    return _wstring_at_addr(addr)
+
+            def _setvalue(self, value):
+                if isinstance(value, str):
+                    array = _rawffi.Array('u')(len(value)+1, value)
+                    value = array.buffer
+                    # XXX free 'array' later
+                elif value is None:
+                    value = 0
+                self._buffer[0] = value
+            result.value = property(_getvalue, _setvalue)
 
         elif tp == 'P':
             # c_void_p

Added: pypy/dist/pypy/lib/app_test/ctypes/test_cast.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/lib/app_test/ctypes/test_cast.py	Fri Jan 25 20:26:31 2008
@@ -0,0 +1,75 @@
+from ctypes import *
+import sys, py
+
+class TestCast:
+
+    def test_array2pointer(self):
+        array = (c_int * 3)(42, 17, 2)
+
+        # casting an array to a pointer works.
+        ptr = cast(array, POINTER(c_int))
+        assert [ptr[i] for i in range(3)] == [42, 17, 2]
+
+        if 2*sizeof(c_short) == sizeof(c_int):
+            ptr = cast(array, POINTER(c_short))
+            if sys.byteorder == "little":
+                assert [ptr[i] for i in range(6)] == (
+                                     [42, 0, 17, 0, 2, 0])
+            else:
+                assert [ptr[i] for i in range(6)] == (
+                                     [0, 42, 0, 17, 0, 2])
+
+    def test_address2pointer(self):
+        array = (c_int * 3)(42, 17, 2)
+
+        address = addressof(array)
+        ptr = cast(c_void_p(address), POINTER(c_int))
+        assert [ptr[i] for i in range(3)] == [42, 17, 2]
+
+        ptr = cast(address, POINTER(c_int))
+        assert [ptr[i] for i in range(3)] == [42, 17, 2]
+
+    def test_p2a_objects(self):
+        py.test.skip("keepalive logic")
+        array = (c_char_p * 5)()
+        assert array._objects == None
+        array[0] = "foo bar"
+        assert array._objects == {'0': "foo bar"}
+
+        p = cast(array, POINTER(c_char_p))
+        # array and p share a common _objects attribute
+        assert p._objects is array._objects
+        assert array._objects == {'0': "foo bar", id(array): array}
+        p[0] = "spam spam"
+        assert p._objects == {'0': "spam spam", id(array): array}
+        assert array._objects is p._objects
+        p[1] = "foo bar"
+        assert p._objects == {'1': 'foo bar', '0': "spam spam", id(array): array}
+        assert array._objects is p._objects
+
+    def test_other(self):
+        p = cast((c_int * 4)(1, 2, 3, 4), POINTER(c_int))
+        assert p[:4] == [1,2, 3, 4]
+        c_int()
+        assert p[:4] == [1, 2, 3, 4]
+        p[2] = 96
+        assert p[:4] == [1, 2, 96, 4]
+        c_int()
+        assert p[:4] == [1, 2, 96, 4]
+
+    def test_char_p(self):
+        # This didn't work: bad argument to internal function
+        s = c_char_p("hiho")
+        assert cast(cast(s, c_void_p), c_char_p).value == (
+                             "hiho")
+
+    try:
+        c_wchar_p
+    except NameError:
+        pass
+    else:
+        def test_wchar_p(self):
+            py.test.skip("XXX reenable")
+            s = c_wchar_p("hiho")
+            assert cast(cast(s, c_void_p), c_wchar_p).value == (
+                                 "hiho")



More information about the Pypy-commit mailing list