[pypy-svn] r50619 - in pypy/branch/applevel-ctypes2/pypy/module/_rawffi: . test
arigo at codespeak.net
arigo at codespeak.net
Tue Jan 15 11:37:58 CET 2008
Author: arigo
Date: Tue Jan 15 11:37:57 2008
New Revision: 50619
Added:
pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py (contents, props changed)
Modified:
pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py
pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py
Log:
(cfbolz, arigo)
Fix size and alignment of structures, and expose this information
to app-level.
Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py (original)
+++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py Tue Jan 15 11:37:57 2008
@@ -29,37 +29,49 @@
fields.append((name, code))
return fields
-def size_and_pos(fields):
- size = intmask(TYPEMAP[fields[0][1]].c_size)
- pos = [0]
- for i in range(1, len(fields)):
+def round_up(size, alignment):
+ return (size + alignment - 1) & -alignment
+
+def size_alignment_pos(fields):
+ size = 0
+ alignment = 1
+ pos = []
+ for i in range(len(fields)):
field_desc = TYPEMAP[fields[i][1]]
- missing = size % intmask(field_desc.c_alignment)
- if missing:
- size += intmask(field_desc.c_alignment) - missing
+ size = round_up(size, intmask(field_desc.c_alignment))
+ alignment = max(alignment, intmask(field_desc.c_alignment))
pos.append(size)
size += intmask(field_desc.c_size)
- return size, pos
+ size = round_up(size, alignment)
+ return size, alignment, pos
class W_Structure(Wrappable):
def __init__(self, space, w_fields):
fields = unpack_fields(space, w_fields)
- name_to_offset = {}
+ name_to_index = {}
for i in range(len(fields)):
name, letter = fields[i]
if letter not in TYPEMAP:
raise OperationError(space.w_ValueError, space.wrap(
"Unkown type letter %s" % (letter,)))
- if name in name_to_offset:
+ if name in name_to_index:
raise OperationError(space.w_ValueError, space.wrap(
"duplicate field name %s" % (name, )))
- name_to_offset[name] = i
- size, pos = size_and_pos(fields)
+ name_to_index[name] = i
+ size, alignment, pos = size_alignment_pos(fields)
self.size = size
+ self.alignment = alignment
self.ll_positions = pos
self.fields = fields
- self.name_to_offset = name_to_offset
+ self.name_to_index = name_to_index
+
+ def getindex(self, space, attr):
+ try:
+ return self.name_to_index[attr]
+ except KeyError:
+ raise OperationError(space.w_AttributeError, space.wrap(
+ "C Structure has no attribute %s" % attr))
def descr_call(self, space, __args__):
args_w, kwargs_w = __args__.unpack()
@@ -68,20 +80,28 @@
space.w_TypeError,
space.wrap("Structure accepts only keyword arguments as field initializers"))
return space.wrap(W_StructureInstance(space, self, 0, kwargs_w))
+ descr_call.unwrap_spec = ['self', ObjSpace, Arguments]
def fromaddress(self, space, address):
return space.wrap(W_StructureInstance(space, self, address, None))
fromaddress.unwrap_spec = ['self', ObjSpace, int]
+ def descr_getfieldoffset(self, space, attr):
+ index = self.getindex(space, attr)
+ return space.wrap(self.ll_positions[index])
+ descr_getfieldoffset.unwrap_spec = ['self', ObjSpace, str]
+
def descr_new_structure(space, w_type, w_fields):
return space.wrap(W_Structure(space, w_fields))
W_Structure.typedef = TypeDef(
'Structure',
__new__ = interp2app(descr_new_structure),
- __call__ = interp2app(W_Structure.descr_call,
- unwrap_spec=['self', ObjSpace, Arguments]),
- fromaddress = interp2app(W_Structure.fromaddress)
+ __call__ = interp2app(W_Structure.descr_call),
+ fromaddress = interp2app(W_Structure.fromaddress),
+ size = interp_attrproperty('size', W_Structure),
+ alignment = interp_attrproperty('alignment', W_Structure),
+ getfieldoffset = interp2app(W_Structure.descr_getfieldoffset),
)
W_Structure.typedef.acceptable_as_base_class = False
@@ -106,18 +126,10 @@
for field, w_value in fieldinits_w.iteritems():
self.setattr(space, field, w_value)
-
- def getindex(self, space, attr):
- try:
- return self.shape.name_to_offset[attr]
- except KeyError:
- raise OperationError(space.w_AttributeError, space.wrap(
- "C Structure has no attribute %s" % attr))
-
def getattr(self, space, attr):
if not self.ll_buffer:
raise segfault_exception(space, "accessing NULL pointer")
- i = self.getindex(space, attr)
+ i = self.shape.getindex(space, attr)
_, c = self.shape.fields[i]
return wrap_value(space, cast_pos, self, i, c)
getattr.unwrap_spec = ['self', ObjSpace, str]
@@ -125,7 +137,7 @@
def setattr(self, space, attr, w_value):
if not self.ll_buffer:
raise segfault_exception(space, "accessing NULL pointer")
- i = self.getindex(space, attr)
+ i = self.shape.getindex(space, attr)
_, c = self.shape.fields[i]
unwrap_value(space, push_field, self, i, c, w_value)
setattr.unwrap_spec = ['self', ObjSpace, str, W_Root]
Added: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py
==============================================================================
--- (empty file)
+++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py Tue Jan 15 11:37:57 2008
@@ -0,0 +1,25 @@
+from pypy.conftest import gettestobjspace
+import os, sys, py
+
+def setup_module(mod):
+ if sys.platform != 'linux2':
+ py.test.skip("Linux only tests by now")
+
+class AppTestNested:
+ def setup_class(cls):
+ space = gettestobjspace(usemodules=('_rawffi','struct'))
+ cls.space = space
+
+ def test_inspect_structure(self):
+ import _rawffi, struct
+ align = max(struct.calcsize("i"), struct.calcsize("P"))
+ assert align & (align-1) == 0, "not a power of 2??"
+ def round_up(x):
+ return (x+align-1) & -align
+
+ S = _rawffi.Structure([('a', 'i'), ('b', 'P'), ('c', 'c')])
+ assert S.size == round_up(struct.calcsize("iPc"))
+ assert S.alignment == align
+ assert S.getfieldoffset('a') == 0
+ assert S.getfieldoffset('b') == align
+ assert S.getfieldoffset('c') == round_up(struct.calcsize("iP"))
Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py (original)
+++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py Tue Jan 15 11:37:57 2008
@@ -1,7 +1,7 @@
-from pypy.module._rawffi.structure import size_and_pos
+from pypy.module._rawffi.structure import size_alignment_pos, TYPEMAP
-sizeof = lambda x : size_and_pos(x)[0]
+sizeof = lambda x : size_alignment_pos(x)[0]
def unpack(desc):
return [('x', i) for i in desc]
@@ -10,8 +10,14 @@
s_c = sizeof(unpack('c'))
s_l = sizeof(unpack('l'))
s_q = sizeof(unpack('q'))
+ alignment_of_q = TYPEMAP['q'].c_alignment
+ assert alignment_of_q >= 4
assert sizeof(unpack('cl')) == 2*s_l
- assert sizeof(unpack('cq')) == s_q + s_l
- assert sizeof(unpack('ccq')) == s_q + s_l
- assert sizeof(unpack('ccccq')) == 4 * s_c + s_q
-
+ assert sizeof(unpack('cq')) == alignment_of_q + s_q
+ assert sizeof(unpack('ccq')) == alignment_of_q + s_q
+ assert sizeof(unpack('cccq')) == alignment_of_q + s_q
+ assert sizeof(unpack('ccccq')) == alignment_of_q + s_q
+ assert sizeof(unpack('qc')) == s_q + alignment_of_q
+ assert sizeof(unpack('qcc')) == s_q + alignment_of_q
+ assert sizeof(unpack('qccc')) == s_q + alignment_of_q
+ assert sizeof(unpack('qcccc')) == s_q + alignment_of_q
More information about the Pypy-commit
mailing list