[pypy-svn] r72464 - in pypy/branch/rawffi-64/pypy/module/_rawffi: . test
arigo at codespeak.net
arigo at codespeak.net
Sat Mar 20 18:56:13 CET 2010
Author: arigo
Date: Sat Mar 20 18:56:11 2010
New Revision: 72464
Modified:
pypy/branch/rawffi-64/pypy/module/_rawffi/array.py
pypy/branch/rawffi-64/pypy/module/_rawffi/interp_rawffi.py
pypy/branch/rawffi-64/pypy/module/_rawffi/structure.py
pypy/branch/rawffi-64/pypy/module/_rawffi/test/test__rawffi.py
Log:
Whack whack until one test passes.
Modified: pypy/branch/rawffi-64/pypy/module/_rawffi/array.py
==============================================================================
--- pypy/branch/rawffi-64/pypy/module/_rawffi/array.py (original)
+++ pypy/branch/rawffi-64/pypy/module/_rawffi/array.py Sat Mar 20 18:56:11 2010
@@ -12,8 +12,8 @@
from pypy.module._rawffi.interp_rawffi import segfault_exception
from pypy.module._rawffi.interp_rawffi import W_DataShape, W_DataInstance
from pypy.module._rawffi.interp_rawffi import unwrap_value, wrap_value
-from pypy.module._rawffi.interp_rawffi import letter2tp
-from pypy.module._rawffi.interp_rawffi import unpack_to_size_alignment
+from pypy.module._rawffi.interp_rawffi import TYPEMAP
+from pypy.module._rawffi.interp_rawffi import unpack_shape_with_length
from pypy.rlib.rarithmetic import intmask, r_uint
def push_elem(ll_array, pos, value):
@@ -27,17 +27,30 @@
return ll_array[pos]
get_elem._annspecialcase_ = 'specialize:arg(2)'
+
class W_Array(W_DataShape):
- def __init__(self, space, itemtp):
- assert isinstance(itemtp, tuple)
- self.space = space
- self.itemtp = itemtp
+ def __init__(self, basicffitype, multiplier=1, itemcode='?'):
+ # 'multiplier' is not the length of the array!
+ # A W_Array represent the C type '*T', which can also represent
+ # the type of pointers to arrays of T. So the following fields
+ # are used to describe T only. It is 'multiplier' times the
+ # 'basicffitype'.
+ self.basicffitype = basicffitype
+ self.multiplier = multiplier
+ # for the W_Arrays that represent simple types only:
+ self.itemcode = itemcode
def allocate(self, space, length, autofree=False):
if autofree:
return W_ArrayInstanceAutoFree(space, self, length)
return W_ArrayInstance(space, self, length)
+ def get_basic_ffi_type(self):
+ return self.basicffitype
+
+ def get_ffi_type_with_length(self):
+ return self.basicffitype, self.multiplier
+
def descr_call(self, space, length, w_items=None, autofree=False):
result = self.allocate(space, length, autofree)
if not space.is_w(w_items, space.w_None):
@@ -50,42 +63,34 @@
for num in range(iterlength):
w_item = items_w[num]
unwrap_value(space, push_elem, result.ll_buffer, num,
- self.itemtp[0], w_item)
+ self.itemcode, w_item)
return space.wrap(result)
def descr_repr(self, space):
- return space.wrap("<_rawffi.Array '%s' (%d, %d)>" % self.itemtp)
+ return space.wrap("<_rawffi.Array '%s' (%d, %d)>" % self.itemcode)
descr_repr.unwrap_spec = ['self', ObjSpace]
def fromaddress(self, space, address, length):
return space.wrap(W_ArrayInstance(space, self, length, address))
fromaddress.unwrap_spec = ['self', ObjSpace, r_uint, int]
- def _size_alignment(self):
- _, itemsize, alignment = self.itemtp
- return itemsize, alignment
-
-class ArrayCache:
- def __init__(self, space):
- self.space = space
- self.cache = {}
- self.array_of_ptr = self.get_array_type(letter2tp(space, 'P'))
-
- def get_array_type(self, itemtp):
- try:
- return self.cache[itemtp]
- except KeyError:
- result = W_Array(self.space, itemtp)
- self.cache[itemtp] = result
- return result
-
-def get_array_cache(space):
- return space.fromcache(ArrayCache)
+PRIMITIVE_ARRAY_TYPES = {}
+for _code in TYPEMAP:
+ PRIMITIVE_ARRAY_TYPES[_code] = W_Array(TYPEMAP[_code], itemcode=_code)
+ARRAY_OF_PTRS = PRIMITIVE_ARRAY_TYPES['P']
def descr_new_array(space, w_type, w_shape):
- itemtp = unpack_to_size_alignment(space, w_shape)
- array_type = get_array_cache(space).get_array_type(itemtp)
- return space.wrap(array_type)
+ shape, length = unpack_shape_with_length(space, w_shape)
+ if length == 1:
+ return shape
+ if shape._array_shapes is None:
+ shape._array_shapes = {}
+ try:
+ result = shape._array_shapes[length]
+ except KeyError:
+ ffitype, lbase = shape.get_ffi_type_with_length()
+ result = shape._array_shapes[length] = W_Array(ffitype, lbase*length)
+ return result
W_Array.typedef = TypeDef(
'Array',
@@ -102,8 +107,7 @@
class W_ArrayInstance(W_DataInstance):
def __init__(self, space, shape, length, address=r_uint(0)):
- _, itemsize, _ = shape.itemtp
- W_DataInstance.__init__(self, space, itemsize * length, address)
+ W_DataInstance.__init__(self, space, shape.size * length, address)
self.length = length
self.shape = shape
@@ -122,7 +126,7 @@
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.itemtp[0], w_value)
+ self.shape.itemcode, w_value)
def descr_setitem(self, space, w_index, w_value):
try:
@@ -141,7 +145,7 @@
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.itemtp)
+ self.shape.itemcode)
def descr_getitem(self, space, w_index):
try:
Modified: pypy/branch/rawffi-64/pypy/module/_rawffi/interp_rawffi.py
==============================================================================
--- pypy/branch/rawffi-64/pypy/module/_rawffi/interp_rawffi.py (original)
+++ pypy/branch/rawffi-64/pypy/module/_rawffi/interp_rawffi.py Sat Mar 20 18:56:11 2010
@@ -52,9 +52,6 @@
def size_alignment(ffi_type):
return intmask(ffi_type.c_size), intmask(ffi_type.c_alignment)
-UNPACKED_TYPECODES = dict([(code, (code,) + size_alignment(field_desc))
- for code, field_desc in TYPEMAP.items()])
-
LL_TYPEMAP = {
'c' : rffi.CHAR,
'u' : lltype.UniChar,
@@ -82,65 +79,41 @@
LL_TYPEMAP['v'] = rffi.SHORT
def letter2tp(space, key):
+ from pypy.module._rawffi.array import PRIMITIVE_ARRAY_TYPES
try:
- return UNPACKED_TYPECODES[key]
+ return PRIMITIVE_ARRAY_TYPES[key]
except KeyError:
raise operationerrfmt(space.w_ValueError,
"Unknown type letter %s", key)
-def _get_type_(space, key):
- try:
- return TYPEMAP[key]
- except KeyError:
- raise operationerrfmt(space.w_ValueError,
- "Unknown type letter %s", key)
-
-def unpack_to_ffi_type(space, w_shape, shape=False):
- resshape = None
+def unpack_simple_shape(space, w_shape):
+ # 'w_shape' must be either a letter or a tuple (struct, 1).
if space.is_true(space.isinstance(w_shape, space.w_str)):
letter = space.str_w(w_shape)
- ffi_type = _get_type_(space, letter)
- if shape:
- from pypy.module._rawffi.array import get_array_cache
- cache = get_array_cache(space)
- resshape = cache.get_array_type(letter2tp(space, letter))
+ return letter2tp(space, letter)
else:
- letter = 'V'
w_shapetype, w_length = space.fixedview(w_shape, expected_length=2)
from pypy.module._rawffi.structure import W_Structure
- resshape = space.interp_w(W_Structure, w_shapetype)
- ffi_type = resshape.get_ffi_type()
- return letter, ffi_type, resshape
+ return space.interp_w(W_Structure, w_shapetype)
-def unpack_to_size_alignment(space, w_shape):
+def unpack_shape_with_length(space, w_shape):
+ # allow 'w_shape' to be a letter or any (shape, number).
if space.is_true(space.isinstance(w_shape, space.w_str)):
letter = space.str_w(w_shape)
- return letter2tp(space, letter)
+ return letter2tp(space, letter), 1
else:
w_shapetype, w_length = space.fixedview(w_shape, expected_length=2)
- resshape = space.interp_w(W_DataShape, w_shapetype)
length = space.int_w(w_length)
- size, alignment = resshape._size_alignment()
- return ('V', length*size, alignment) # value object
+ return space.interp_w(W_DataShape, w_shapetype), length
def unpack_resshape(space, w_restype):
if space.is_w(w_restype, space.w_None):
- resshape = None
- ffi_restype = ffi_type_void
- else:
- tp_letter, ffi_restype, resshape = unpack_to_ffi_type(space,
- w_restype,
- shape=True)
- return ffi_restype, resshape
+ return None
+ return unpack_simple_shape(space, w_restype)
def unpack_argshapes(space, w_argtypes):
- argletters = []
- ffi_argtypes = []
- for w_arg in space.unpackiterable(w_argtypes):
- argletter, ffi_argtype, _ = unpack_to_ffi_type(space, w_arg)
- argletters.append(argletter)
- ffi_argtypes.append(ffi_argtype)
- return ffi_argtypes, argletters
+ return [unpack_simple_shape(space, w_arg)
+ for w_arg in space.unpackiterable(w_argtypes)]
class W_CDLL(Wrappable):
def __init__(self, space, name):
@@ -157,7 +130,7 @@
""" Get a pointer for function name with provided argtypes
and restype
"""
- ffi_restype, resshape = unpack_resshape(space, w_restype)
+ resshape = unpack_resshape(space, w_restype)
w = space.wrap
argtypes_w = space.fixedview(w_argtypes)
w_argtypes = space.newtuple(argtypes_w)
@@ -169,7 +142,12 @@
pass
else:
raise
- ffi_argtypes, argletters = unpack_argshapes(space, w_argtypes)
+ argshapes = unpack_argshapes(space, w_argtypes)
+ ffi_argtypes = [shape.get_basic_ffi_type() for shape in argshapes]
+ if resshape is not None:
+ ffi_restype = resshape.get_basic_ffi_type()
+ else:
+ ffi_restype = ffi_type_void
if space.is_true(space.isinstance(w_name, space.w_str)):
name = space.str_w(w_name)
@@ -194,7 +172,7 @@
raise OperationError(space.w_TypeError, space.wrap(
"function name must be string or integer"))
- w_funcptr = W_FuncPtr(space, ptr, argletters, resshape)
+ w_funcptr = W_FuncPtr(space, ptr, argshapes, resshape)
space.setitem(self.w_cache, w_key, w_funcptr)
return w_funcptr
ptr.unwrap_spec = ['self', ObjSpace, W_Root, W_Root, W_Root, int]
@@ -240,17 +218,22 @@
return OperationError(w_exception, space.wrap(reason))
class W_DataShape(Wrappable):
+ _array_shapes = None
+ size = 0
+ alignment = 0
def allocate(self, space, length, autofree=False):
raise NotImplementedError
- def _size_alignment(self):
+ def get_basic_ffi_type(self):
raise NotImplementedError
-
+
+ def get_ffi_type_with_length(self):
+ return self.get_basic_ffi_type(), 1 # default implementation
+
def descr_size_alignment(self, space, n=1):
- size, alignment = self._size_alignment()
- return space.newtuple([space.wrap(size * n),
- space.wrap(alignment)])
+ return space.newtuple([space.wrap(self.size * n),
+ space.wrap(self.alignment)])
descr_size_alignment.unwrap_spec = ['self', ObjSpace, int]
@@ -269,9 +252,8 @@
return space.wrap(rffi.cast(lltype.Unsigned, self.ll_buffer))
def byptr(self, space):
- from pypy.module._rawffi.array import get_array_cache
- array_of_ptr = get_array_cache(space).array_of_ptr
- array = array_of_ptr.allocate(space, 1)
+ from pypy.module._rawffi.array import ARRAY_OF_PTRS
+ array = ARRAY_OF_PTRS.allocate(space, 1)
array.setitem(space, 0, space.wrap(self))
return space.wrap(array)
byptr.unwrap_spec = ['self', ObjSpace]
@@ -306,12 +288,7 @@
def unwrap_value(space, push_func, add_arg, argdesc, letter, w_arg):
w = space.wrap
- if letter == "d":
- push_func(add_arg, argdesc, space.float_w(w_arg))
- elif letter == "f":
- push_func(add_arg, argdesc, rffi.cast(rffi.FLOAT,
- space.float_w(w_arg)))
- elif letter in TYPEMAP_PTR_LETTERS:
+ if letter in TYPEMAP_PTR_LETTERS:
# check for NULL ptr
datainstance = space.interpclass_w(w_arg)
if isinstance(datainstance, W_DataInstance):
@@ -319,6 +296,11 @@
else:
ptr = unwrap_truncate_int(rffi.VOIDP, space, w_arg)
push_func(add_arg, argdesc, ptr)
+ elif letter == "d":
+ push_func(add_arg, argdesc, space.float_w(w_arg))
+ elif letter == "f":
+ push_func(add_arg, argdesc, rffi.cast(rffi.FLOAT,
+ space.float_w(w_arg)))
elif letter == "c":
s = space.str_w(w_arg)
if len(s) != 1:
@@ -347,8 +329,7 @@
ll_typemap_iter = unrolling_iterable(LL_TYPEMAP.items())
-def wrap_value(space, func, add_arg, argdesc, tp):
- letter, _, _ = tp
+def wrap_value(space, func, add_arg, argdesc, letter):
for c, ll_type in ll_typemap_iter:
if letter == c:
if c in TYPEMAP_PTR_LETTERS:
@@ -365,9 +346,9 @@
wrap_value._annspecialcase_ = 'specialize:arg(1)'
class W_FuncPtr(Wrappable):
- def __init__(self, space, ptr, argletters, resshape):
+ def __init__(self, space, ptr, argshapes, resshape):
self.ptr = ptr
- self.argletters = argletters
+ self.argshapes = argshapes
self.resshape = resshape
def getbuffer(space, self):
@@ -393,16 +374,17 @@
def call(self, space, args_w):
from pypy.module._rawffi.array import W_ArrayInstance
from pypy.module._rawffi.structure import W_StructureInstance
+ from pypy.module._rawffi.structure import W_Structure
argnum = len(args_w)
- if argnum != len(self.argletters):
+ if argnum != len(self.argshapes):
msg = "Wrong number of arguments: expected %d, got %d"
raise operationerrfmt(space.w_TypeError, msg,
- len(self.argletters), argnum)
+ len(self.argshapes), argnum)
args_ll = []
for i in range(argnum):
- argletter = self.argletters[i]
+ argshape = self.argshapes[i]
w_arg = args_w[i]
- if argletter == 'V': # by value object
+ if isinstance(argshape, W_Structure): # argument by value
arg = space.interp_w(W_StructureInstance, w_arg)
xsize, xalignment = size_alignment(self.ptr.argtypes[i])
if (arg.shape.size != xsize or
@@ -420,7 +402,8 @@
"got length %d")
raise operationerrfmt(space.w_TypeError, msg,
i+1, arg.length)
- letter = arg.shape.itemtp[0]
+ argletter = argshape.itemcode
+ letter = arg.shape.itemcode
if letter != argletter:
if not (argletter in TYPEMAP_PTR_LETTERS and
letter in TYPEMAP_PTR_LETTERS):
Modified: pypy/branch/rawffi-64/pypy/module/_rawffi/structure.py
==============================================================================
--- pypy/branch/rawffi-64/pypy/module/_rawffi/structure.py (original)
+++ pypy/branch/rawffi-64/pypy/module/_rawffi/structure.py Sat Mar 20 18:56:11 2010
@@ -13,7 +13,7 @@
from pypy.module._rawffi.interp_rawffi import segfault_exception
from pypy.module._rawffi.interp_rawffi import W_DataShape, W_DataInstance
from pypy.module._rawffi.interp_rawffi import wrap_value, unwrap_value
-from pypy.module._rawffi.interp_rawffi import unpack_to_size_alignment
+#from pypy.module._rawffi.interp_rawffi import unpack_to_size_alignment
from pypy.rlib import libffi
from pypy.rlib.rarithmetic import intmask, r_uint
@@ -99,13 +99,10 @@
return space.wrap(self.ll_positions[index])
descr_fieldoffset.unwrap_spec = ['self', ObjSpace, str]
- def _size_alignment(self):
- return self.size, self.alignment
-
# get the corresponding ffi_type
ffi_type = lltype.nullptr(libffi.FFI_TYPE_P.TO)
- def get_ffi_type(self):
+ def get_basic_ffi_type(self):
if not self.ffi_type:
self.ffi_type = libffi.make_struct_ffitype(self.size,
self.alignment)
Modified: pypy/branch/rawffi-64/pypy/module/_rawffi/test/test__rawffi.py
==============================================================================
--- pypy/branch/rawffi-64/pypy/module/_rawffi/test/test__rawffi.py (original)
+++ pypy/branch/rawffi-64/pypy/module/_rawffi/test/test__rawffi.py Sat Mar 20 18:56:11 2010
@@ -141,6 +141,16 @@
return inp;
}
+ struct s2a {
+ int bah[2];
+ };
+
+ struct s2a perturbarray(struct s2a inp) {
+ inp.bah[0] *= 4;
+ inp.bah[1] *= 5;
+ return inp;
+ }
+
int AAA_first_ordinal_function()
{
return 42;
@@ -157,7 +167,7 @@
allocate_array
static_int static_double
sum_x_y
- give perturb
+ give perturb perturbarray
AAA_first_ordinal_function
""".split()
eci = ExternalCompilationInfo(export_symbols=symbols)
@@ -819,19 +829,22 @@
assert 0, "Did not raise"
def test_struct_byvalue(self):
- if self.isx86_64:
- skip("Segfaults on x86_64 because small structures "
- "may be passed in registers and "
- "c_elements must not be null")
+ #if self.isx86_64:
+ # skip("Segfaults on x86_64 because small structures "
+ # "may be passed in registers and "
+ # "c_elements must not be null")
- import _rawffi
+ import _rawffi, sys
X_Y = _rawffi.Structure([('x', 'l'), ('y', 'l')])
x_y = X_Y()
lib = _rawffi.CDLL(self.lib_name)
+ print >> sys.stderr, "getting..."
sum_x_y = lib.ptr('sum_x_y', [(X_Y, 1)], 'l')
x_y.x = 200
x_y.y = 220
+ print >> sys.stderr, "calling..."
res = sum_x_y(x_y)
+ print >> sys.stderr, "done"
assert res[0] == 420
x_y.free()
@@ -871,6 +884,41 @@
s2h.free()
+ def test_ret_struct_containing_array(self):
+ if self.isx86_64:
+ skip("Segfaults on x86_64 because small structures "
+ "may be passed in registers and "
+ "c_elements must not be null")
+
+ import _rawffi
+ AoI = _rawffi.Array('i')
+ S2A = _rawffi.Structure([('bah', (AoI, 2))])
+ s2a = S2A()
+ lib = _rawffi.CDLL(self.lib_name)
+ perturbarray = lib.ptr('perturbarray', [(S2A, 1)], (S2A, 1))
+ s2a.x = 100
+ a2a.y = 200
+ res = perturbarray(s2a)
+ assert isinstance(res, _rawffi.StructureInstanceAutoFree)
+ assert res.shape is S2H
+ assert res.x == 13
+ assert res.y == 17
+ a1.free()
+ a2.free()
+
+ s2h.x = 7
+ s2h.y = 11
+ perturb = lib.ptr('perturb', [(S2H, 1)], (S2H, 1))
+ res = perturb(s2h)
+ assert isinstance(res, _rawffi.StructureInstanceAutoFree)
+ assert res.shape is S2H
+ assert res.x == 14
+ assert res.y == 33
+ assert s2h.x == 7
+ assert s2h.y == 11
+
+ s2h.free()
+
def test_buffer(self):
import _rawffi
S = _rawffi.Structure((40, 1))
More information about the Pypy-commit
mailing list