[pypy-svn] r50622 - in pypy/branch/applevel-ctypes2/pypy/module/_rawffi: . test
arigo at codespeak.net
arigo at codespeak.net
Tue Jan 15 12:41:50 CET 2008
Author: arigo
Date: Tue Jan 15 12:41:48 2008
New Revision: 50622
Modified:
pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py
pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py
pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py
pypy/branch/applevel-ctypes2/pypy/module/_rawffi/structure.py
pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py
pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_struct.py
Log:
(cfbolz, fijal, arigo)
Support nested structures inside other structures.
Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py (original)
+++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/__init__.py Tue Jan 15 12:41:48 2008
@@ -16,7 +16,6 @@
'StructureInstance' : 'structure.W_StructureInstance',
'Array' : 'array.W_Array',
'ArrayInstance' : 'array.W_ArrayInstance',
- '_get_type' : 'interp_rawffi._w_get_type',
'sizeof' : 'interp_rawffi.sizeof',
'alignment' : 'interp_rawffi.alignment',
'charp2string' : 'interp_rawffi.charp2string',
Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py (original)
+++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/array.py Tue Jan 15 12:41:48 2008
@@ -11,8 +11,8 @@
from pypy.interpreter.error import OperationError, wrap_oserror
from pypy.module._rawffi.interp_rawffi import segfault_exception
from pypy.module._rawffi.interp_rawffi import W_DataInstance
-from pypy.module._rawffi.interp_rawffi import unwrap_value, wrap_value, _get_type,\
- TYPEMAP
+from pypy.module._rawffi.interp_rawffi import unwrap_value, wrap_value
+from pypy.module._rawffi.interp_rawffi import unpack_typecode, letter2tp
from pypy.rlib.rarithmetic import intmask
def push_elem(ll_array, pos, value):
@@ -27,10 +27,10 @@
get_elem._annspecialcase_ = 'specialize:arg(2)'
class W_Array(Wrappable):
- def __init__(self, space, of):
+ def __init__(self, space, itemtp):
+ assert isinstance(itemtp, tuple)
self.space = space
- self.of = of
- self.itemsize = intmask(TYPEMAP[of].c_size)
+ self.itemtp = itemtp
def allocate(self, space, length):
return W_ArrayInstance(space, self, length)
@@ -46,8 +46,8 @@
" array length"))
for num in range(iterlength):
w_item = items_w[num]
- unwrap_value(space, push_elem, result.ll_buffer, num, self.of,
- w_item)
+ unwrap_value(space, push_elem, result.ll_buffer, num,
+ self.itemtp, w_item)
return space.wrap(result)
def fromaddress(self, space, address, length):
@@ -58,27 +58,28 @@
def __init__(self, space):
self.space = space
self.cache = {}
- self.array_of_ptr = self.get_array_type('P')
+ self.array_of_ptr = self.get_array_type(letter2tp(space, 'P'))
- def get_array_type(self, of):
+ def get_array_type(self, itemtp):
try:
- return self.cache[of]
+ return self.cache[itemtp]
except KeyError:
- _get_type(self.space, of)
- result = W_Array(self.space, of)
- self.cache[of] = result
+ result = W_Array(self.space, itemtp)
+ self.cache[itemtp] = result
return result
def get_array_cache(space):
return space.fromcache(ArrayCache)
-def descr_new_array(space, w_type, of):
- array_type = get_array_cache(space).get_array_type(of)
+def descr_new_array(space, w_type, w_itemtp):
+ itemtp = unpack_typecode(space, w_itemtp)
+ array_type = get_array_cache(space).get_array_type(itemtp)
return space.wrap(array_type)
W_Array.typedef = TypeDef(
'Array',
- __new__ = interp2app(descr_new_array, unwrap_spec=[ObjSpace, W_Root, str]),
+ __new__ = interp2app(descr_new_array,
+ unwrap_spec=[ObjSpace, W_Root, W_Root]),
__call__ = interp2app(W_Array.descr_call,
unwrap_spec=['self', ObjSpace, int, W_Root]),
fromaddress = interp2app(W_Array.fromaddress),
@@ -89,7 +90,8 @@
class W_ArrayInstance(W_DataInstance):
def __init__(self, space, shape, length, address=0):
- W_DataInstance.__init__(self, space, shape.itemsize * length, address)
+ _, itemsize, _ = shape.itemtp
+ W_DataInstance.__init__(self, space, itemsize * length, address)
self.length = length
self.shape = shape
@@ -98,14 +100,15 @@
def setitem(self, space, num, w_value):
if num >= self.length or num < 0:
raise OperationError(space.w_IndexError, space.w_None)
- unwrap_value(space, push_elem, self.ll_buffer, num, self.shape.of,
+ unwrap_value(space, push_elem, self.ll_buffer, num, self.shape.itemtp,
w_value)
setitem.unwrap_spec = ['self', ObjSpace, int, W_Root]
def getitem(self, space, num):
if num >= self.length or num < 0:
raise OperationError(space.w_IndexError, space.w_None)
- return wrap_value(space, get_elem, self.ll_buffer, num, self.shape.of)
+ return wrap_value(space, get_elem, self.ll_buffer, num,
+ self.shape.itemtp)
getitem.unwrap_spec = ['self', ObjSpace, int]
W_ArrayInstance.typedef = TypeDef(
Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py (original)
+++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/interp_rawffi.py Tue Jan 15 12:41:48 2008
@@ -12,6 +12,7 @@
from pypy.module.struct.standardfmttable import min_max_acc_method
from pypy.module.struct.nativefmttable import native_fmttable
from pypy.tool.sourcetools import func_with_new_name
+from pypy.rlib.rarithmetic import intmask
class FfiValueError(Exception):
def __init__(self, msg):
@@ -54,6 +55,11 @@
}
TYPEMAP_PTR_LETTERS = "POsz"
+UNPACKED_TYPECODES = dict([(code, (code,
+ intmask(field_desc.c_size),
+ intmask(field_desc.c_alignment)))
+ for code, field_desc in TYPEMAP.items()])
+
LL_TYPEMAP = {
'c' : rffi.CHAR,
'b' : rffi.SIGNEDCHAR,
@@ -75,18 +81,19 @@
'v' : lltype.Void,
}
-def _get_type(space, key):
+def letter2tp(space, key):
try:
- return TYPEMAP[key]
+ return UNPACKED_TYPECODES[key]
except KeyError:
raise OperationError(space.w_ValueError, space.wrap(
"Unknown type letter %s" % (key,)))
- return lltype.nullptr(FFI_TYPE_P.TO)
-def _w_get_type(space, key):
- _get_type(space, key)
- return space.w_None
-_w_get_type.unwrap_spec = [ObjSpace, str]
+def _get_type_(space, key):
+ try:
+ return TYPEMAP[key]
+ except KeyError:
+ raise OperationError(space.w_ValueError, space.wrap(
+ "Unknown type letter %s" % (key,)))
class W_CDLL(Wrappable):
def __init__(self, space, name):
@@ -97,7 +104,7 @@
def get_type(self, key):
space = self.space
- return _get_type(space, key)
+ return _get_type_(space, key)
def ptr(self, space, name, w_argtypes, w_restype):
""" Get a pointer for function name with provided argtypes
@@ -188,6 +195,14 @@
w_exception = space.getattr(w_mod, space.wrap("SegfaultException"))
return OperationError(w_exception, space.wrap(reason))
+def unpack_typecode(space, w_typecode):
+ if space.is_true(space.isinstance(w_typecode, space.w_str)):
+ letter = space.str_w(w_typecode)
+ return letter2tp(space, letter)
+ else:
+ w_size, w_align = space.unpacktuple(w_typecode, expected_length=2)
+ return ('?', space.int_w(w_size), space.int_w(w_align))
+
class W_DataInstance(Wrappable):
def __init__(self, space, size, address=0):
@@ -217,20 +232,21 @@
def unwrap_value(space, push_func, add_arg, argdesc, tp, w_arg):
+ letter, _, _ = tp
w = space.wrap
- if tp == "d":
+ if letter == "d":
push_func(add_arg, argdesc, space.float_w(w_arg))
- elif tp == "f":
+ elif letter == "f":
push_func(add_arg, argdesc, rffi.cast(rffi.FLOAT,
space.float_w(w_arg)))
- elif tp in TYPEMAP_PTR_LETTERS:
+ elif letter in TYPEMAP_PTR_LETTERS:
# check for NULL ptr
if space.is_true(space.isinstance(w_arg, space.w_int)):
push_func(add_arg, argdesc, rffi.cast(rffi.VOIDP, space.int_w(w_arg)))
else:
datainstance = space.interp_w(W_DataInstance, w_arg)
push_func(add_arg, argdesc, datainstance.ll_buffer)
- elif tp == "c":
+ elif letter == "c":
s = space.str_w(w_arg)
if len(s) != 1:
raise OperationError(space.w_TypeError, w(
@@ -239,7 +255,7 @@
push_func(add_arg, argdesc, val)
else:
for c, checker in unroll_size_checkers:
- if tp == c:
+ if letter == c:
if c == "q":
val = space.r_longlong_w(w_arg)
elif c == "Q":
@@ -254,14 +270,18 @@
raise OperationError(space.w_ValueError, w(e.msg))
TP = LL_TYPEMAP[c]
push_func(add_arg, argdesc, rffi.cast(TP, val))
-
+ return
+ else:
+ raise OperationError(space.w_TypeError,
+ space.wrap("cannot directly write value"))
unwrap_value._annspecialcase_ = 'specialize:arg(1)'
ll_typemap_iter = unrolling_iterable(LL_TYPEMAP.items())
def wrap_value(space, func, add_arg, argdesc, tp):
+ letter, _, _ = tp
for c, ll_type in ll_typemap_iter:
- if tp == c:
+ if letter == c:
if c in TYPEMAP_PTR_LETTERS:
res = func(add_arg, argdesc, rffi.VOIDP)
return space.wrap(rffi.cast(lltype.Signed, res))
@@ -277,7 +297,8 @@
ll_type)))
else:
return space.wrap(intmask(func(add_arg, argdesc, ll_type)))
- return space.w_None
+ raise OperationError(space.w_TypeError,
+ space.wrap("cannot directly read value"))
wrap_value._annspecialcase_ = 'specialize:arg(1)'
class W_FuncPtr(Wrappable):
@@ -286,7 +307,7 @@
self.ptr = ptr
if restype != 'v':
cache = get_array_cache(space)
- self.resarray = cache.get_array_type(restype)
+ self.resarray = cache.get_array_type(letter2tp(space, restype))
else:
self.resarray = None
self.argtypes = argtypes
@@ -307,9 +328,9 @@
msg = ("Argument %d should be an array of length 1, "
"got length %d" % (i+1, arg.length))
raise OperationError(space.w_TypeError, space.wrap(msg))
- if arg.shape.of != argtype:
+ if arg.shape.itemtp[0] != argtype:
msg = "Argument %d should be typecode %s, got %s" % (
- i+1, argtype, arg.shape.of)
+ i+1, argtype, arg.shape.itemtp[0])
raise OperationError(space.w_TypeError, space.wrap(msg))
args_ll.append(arg.ll_buffer)
# XXX we could avoid the intermediate list args_ll
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 12:41:48 2008
@@ -12,8 +12,8 @@
from pypy.interpreter.error import OperationError, wrap_oserror
from pypy.module._rawffi.interp_rawffi import segfault_exception
from pypy.module._rawffi.interp_rawffi import W_DataInstance
-from pypy.module._rawffi.interp_rawffi import wrap_value, unwrap_value, _get_type,\
- TYPEMAP
+from pypy.module._rawffi.interp_rawffi import wrap_value, unwrap_value
+from pypy.module._rawffi.interp_rawffi import unpack_typecode
from pypy.rlib.rarithmetic import intmask
def unpack_fields(space, w_fields):
@@ -24,9 +24,9 @@
if not len(l_w) == 2:
raise OperationError(space.w_ValueError, space.wrap(
"Expected list of 2-size tuples"))
- name, code = space.str_w(l_w[0]), space.str_w(l_w[1])
- _get_type(space, code) # be paranoid about types
- fields.append((name, code))
+ name = space.str_w(l_w[0])
+ tp = unpack_typecode(space, l_w[1])
+ fields.append((name, tp))
return fields
def round_up(size, alignment):
@@ -36,12 +36,11 @@
size = 0
alignment = 1
pos = []
- for i in range(len(fields)):
- field_desc = TYPEMAP[fields[i][1]]
- size = round_up(size, intmask(field_desc.c_alignment))
- alignment = max(alignment, intmask(field_desc.c_alignment))
+ for fieldname, (letter, fieldsize, fieldalignment) in fields:
+ size = round_up(size, fieldalignment)
+ alignment = max(alignment, fieldalignment)
pos.append(size)
- size += intmask(field_desc.c_size)
+ size += intmask(fieldsize)
size = round_up(size, alignment)
return size, alignment, pos
@@ -51,10 +50,7 @@
fields = unpack_fields(space, w_fields)
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,)))
+ name, tp = fields[i]
if name in name_to_index:
raise OperationError(space.w_ValueError, space.wrap(
"duplicate field name %s" % (name, )))
@@ -91,6 +87,11 @@
return space.wrap(self.ll_positions[index])
descr_getfieldoffset.unwrap_spec = ['self', ObjSpace, str]
+ def descr_gettypecode(self, space):
+ return space.newtuple([space.wrap(self.size),
+ space.wrap(self.alignment)])
+ descr_gettypecode.unwrap_spec = ['self', ObjSpace]
+
def descr_new_structure(space, w_type, w_fields):
return space.wrap(W_Structure(space, w_fields))
@@ -102,6 +103,7 @@
size = interp_attrproperty('size', W_Structure),
alignment = interp_attrproperty('alignment', W_Structure),
getfieldoffset = interp2app(W_Structure.descr_getfieldoffset),
+ gettypecode = interp2app(W_Structure.descr_gettypecode),
)
W_Structure.typedef.acceptable_as_base_class = False
@@ -130,18 +132,24 @@
if not self.ll_buffer:
raise segfault_exception(space, "accessing NULL pointer")
i = self.shape.getindex(space, attr)
- _, c = self.shape.fields[i]
- return wrap_value(space, cast_pos, self, i, c)
+ _, tp = self.shape.fields[i]
+ return wrap_value(space, cast_pos, self, i, tp)
getattr.unwrap_spec = ['self', ObjSpace, str]
def setattr(self, space, attr, w_value):
if not self.ll_buffer:
raise segfault_exception(space, "accessing NULL pointer")
i = self.shape.getindex(space, attr)
- _, c = self.shape.fields[i]
- unwrap_value(space, push_field, self, i, c, w_value)
+ _, tp = self.shape.fields[i]
+ unwrap_value(space, push_field, self, i, tp, w_value)
setattr.unwrap_spec = ['self', ObjSpace, str, W_Root]
+ def descr_fieldaddress(self, space, attr):
+ i = self.shape.getindex(space, attr)
+ ptr = rffi.ptradd(self.ll_buffer, self.shape.ll_positions[i])
+ return space.wrap(rffi.cast(lltype.Signed, ptr))
+ descr_fieldaddress.unwrap_spec = ['self', ObjSpace, str]
+
W_StructureInstance.typedef = TypeDef(
'StructureInstance',
@@ -151,6 +159,7 @@
free = interp2app(W_StructureInstance.free),
shape = interp_attrproperty('shape', W_StructureInstance),
byptr = interp2app(W_StructureInstance.byptr),
+ fieldaddress= interp2app(W_StructureInstance.descr_fieldaddress),
)
W_StructureInstance.typedef.acceptable_as_base_class = False
Modified: pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py (original)
+++ pypy/branch/applevel-ctypes2/pypy/module/_rawffi/test/test_nested.py Tue Jan 15 12:41:48 2008
@@ -23,3 +23,23 @@
assert S.getfieldoffset('a') == 0
assert S.getfieldoffset('b') == align
assert S.getfieldoffset('c') == round_up(struct.calcsize("iP"))
+ assert S.gettypecode() == (S.size, S.alignment)
+
+ def test_nested_structures(self):
+ import _rawffi
+ S1 = _rawffi.Structure([('a', 'i'), ('b', 'P'), ('c', 'c')])
+ S = _rawffi.Structure([('x', 'c'), ('s1', S1.gettypecode())])
+ assert S.size == S1.alignment + S1.size
+ assert S.alignment == S1.alignment
+ assert S.getfieldoffset('x') == 0
+ assert S.getfieldoffset('s1') == S1.alignment
+ s = S()
+ s.x = 'G'
+ raises(TypeError, 's.s1')
+ assert s.fieldaddress('s1') == s.buffer + S.getfieldoffset('s1')
+ s1 = S1.fromaddress(s.fieldaddress('s1'))
+ s1.c = 'H'
+ rawbuf = _rawffi.Array('c').fromaddress(s.buffer, S.size)
+ assert rawbuf[0] == 'G'
+ assert rawbuf[S1.alignment + S1.getfieldoffset('c')] == 'H'
+ s.free()
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 12:41:48 2008
@@ -1,10 +1,11 @@
-from pypy.module._rawffi.structure import size_alignment_pos, TYPEMAP
+from pypy.module._rawffi.structure import size_alignment_pos
+from pypy.module._rawffi.interp_rawffi import TYPEMAP, letter2tp
sizeof = lambda x : size_alignment_pos(x)[0]
def unpack(desc):
- return [('x', i) for i in desc]
+ return [('x', letter2tp('space', i)) for i in desc]
def test_sizeof():
s_c = sizeof(unpack('c'))
More information about the Pypy-commit
mailing list