[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