[pypy-svn] pypy fast-forward: Fix Structure.__getattr__ for bitfield members:

amauryfa commits-noreply at bitbucket.org
Mon Jan 3 14:41:50 CET 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: fast-forward
Changeset: r40336:1fae46f57908
Date: 2011-01-03 10:11 +0100
http://bitbucket.org/pypy/pypy/changeset/1fae46f57908/

Log:	Fix Structure.__getattr__ for bitfield members: can't take the
	address, directly return the value. Also fix sign issues.

	Most ctypes.test_bitfields tests pass.

diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -220,10 +220,14 @@
             field = self._fieldtypes[name]
         except KeyError:
             return _CData.__getattribute__(self, name)
-        fieldtype = field.ctype
-        offset = field.num
-        suba = self._subarray(fieldtype, name)
-        return fieldtype._CData_output(suba, self, offset)
+        if field.size >> 16:
+            # bitfield member, use direct access
+            return self._buffer.__getattr__(name)
+        else:
+            fieldtype = field.ctype
+            offset = field.num
+            suba = self._subarray(fieldtype, name)
+            return fieldtype._CData_output(suba, self, offset)
 
     def _get_buffer_for_param(self):
         return self

diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -472,9 +472,17 @@
         x.C = 0xf
         assert x.A == 1
         assert x.B == 3
-        assert x.C == -2
+        assert x.C == -1
         x.free()
 
+        Y = _rawffi.Structure([('a', 'i', 1),
+                               ('b', 'i', 30),
+                               ('c', 'i', 1)])
+        y = Y()
+        y.a, y.b, y.c = -1, -7, 0
+        assert (y.a, y.b, y.c) == (-1, -7, 0)
+        y.free()
+
     def test_array(self):
         import _rawffi
         lib = _rawffi.CDLL(self.lib_name)

diff --git a/pypy/module/_rawffi/test/test_struct.py b/pypy/module/_rawffi/test/test_struct.py
--- a/pypy/module/_rawffi/test/test_struct.py
+++ b/pypy/module/_rawffi/test/test_struct.py
@@ -53,3 +53,14 @@
 
     assert pos      == [getattr(X, name).offset for (name, _, _) in fields]
     assert bitsizes == [getattr(X, name).size   for (name, _, _) in fields]
+
+def test_bitsizes_longlong():
+    fields = [("a", 'q', 1),
+              ("b", 'q', 62),
+              ("c", 'q', 1)]
+    size, alignment, pos, bitsizes = size_alignment_pos(
+        [(name, letter2tp('space', t), size)
+         for (name, t, size) in fields])
+    assert size == 8
+    assert pos == [0, 0, 0]
+    assert bitsizes == [0x10000, 0x3e0001, 0x1003f]

diff --git a/pypy/module/_rawffi/structure.py b/pypy/module/_rawffi/structure.py
--- a/pypy/module/_rawffi/structure.py
+++ b/pypy/module/_rawffi/structure.py
@@ -181,7 +181,7 @@
         if self.ll_bitsizes and index < len(self.ll_bitsizes):
             return space.wrap(self.ll_bitsizes[index])
         else:
-            return space.wrap(self.fields[index].size)
+            return space.wrap(self.fields[index][1].size)
     descr_fieldsize.unwrap_spec = ['self', ObjSpace, str]
 
     # get the corresponding ffi_type
@@ -284,16 +284,12 @@
             lowbit = LOW_BIT(bitsize)
             if numbits:
                 value = widen(value)
+                value >>= lowbit
+                value &= BIT_MASK(numbits)
                 if ll_t is lltype.Bool or signedtype(ll_t._type):
-                    value >>= lowbit
                     sign = (value >> (numbits - 1)) & 1
-                    value &= BIT_MASK(numbits - 1)
                     if sign:
-                        value = ~value
-                else:
-                    # unsigned is easier
-                    value >>= lowbit
-                    value &= BIT_MASK(numbits)
+                        value = value - (1 << numbits)
                 value = rffi.cast(ll_t, value)
             break
 


More information about the Pypy-commit mailing list