[pypy-commit] pypy default: Merged in palecsandru/pypy_ctypes_char_indexing/ctypes_char_indexing (pull request #552)

arigo pypy.commits at gmail.com
Wed Jun 7 02:06:09 EDT 2017


Author: Armin Rigo <armin.rigo at gmail.com>
Branch: 
Changeset: r91555:60d070027d70
Date: 2017-06-07 06:05 +0000
http://bitbucket.org/pypy/pypy/changeset/60d070027d70/

Log:	Merged in palecsandru/pypy_ctypes_char_indexing/ctypes_char_indexing
	(pull request #552)

	Indexing into char* behaves differently than CPython

diff --git a/lib_pypy/_ctypes/array.py b/lib_pypy/_ctypes/array.py
--- a/lib_pypy/_ctypes/array.py
+++ b/lib_pypy/_ctypes/array.py
@@ -76,12 +76,16 @@
         return self._type_._alignmentofinstances()
 
     def _CData_output(self, resarray, base=None, index=-1):
-        # this seems to be a string if we're array of char, surprise!
-        from ctypes import c_char, c_wchar
-        if self._type_ is c_char:
-            return _rawffi.charp2string(resarray.buffer, self._length_)
-        if self._type_ is c_wchar:
-            return _rawffi.wcharp2unicode(resarray.buffer, self._length_)
+        from _rawffi.alt import types
+        # If a char_p or unichar_p is received, skip the string interpretation
+        if base._ffiargtype != types.Pointer(types.char_p) and \
+           base._ffiargtype != types.Pointer(types.unichar_p):
+            # this seems to be a string if we're array of char, surprise!
+            from ctypes import c_char, c_wchar
+            if self._type_ is c_char:
+                return _rawffi.charp2string(resarray.buffer, self._length_)
+            if self._type_ is c_wchar:
+                return _rawffi.wcharp2unicode(resarray.buffer, self._length_)
         res = self.__new__(self)
         ffiarray = self._ffiarray.fromaddress(resarray.buffer, self._length_)
         res._buffer = ffiarray
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_array.py b/pypy/module/test_lib_pypy/ctypes_tests/test_array.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_array.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_array.py
@@ -138,4 +138,39 @@
         x.y = 3
         y[1] = x
         assert y[1].y == 3
+
+    def test_output_simple(self):
+        A = c_char * 10
+        TP = POINTER(A)
+        x = TP(A())
+        assert repr(x[0]) != "''"
+        assert isinstance(repr(x[0]), bytes)
+
+        A = c_wchar * 10
+        TP = POINTER(A)
+        x = TP(A())
+        assert repr(x[0]) != "''"
+        assert isinstance(repr(x[0]), bytes)
+
+    def test_output_complex_test(self):
+        class Car(Structure):
+            _fields_ = [("brand", c_char * 10),
+                        ("speed", c_float),
+                        ("owner", c_char * 10)]
+
+        assert Car("abcdefghi", 42.0, "12345").brand == "abcdefghi"
+        assert Car("abcdefghio", 42.0, "12345").brand == "abcdefghio"
+        raises(ValueError, Car, "abcdefghiop", 42.0, "12345")
+
+        A = Car._fields_[2][1]
+        TP = POINTER(A)
+        x = TP(A())
+        assert repr(x[0]) != "''"
+        assert isinstance(repr(x[0]), bytes)
+
+        c = Car()
+        c.brand = "abcdex"
+        c.speed = 42.0
+        c.owner = "12345"
+        assert isinstance(repr(c.brand), bytes)
         


More information about the pypy-commit mailing list