[pypy-svn] pypy jitypes2: start the refactoring of _ffi to make it "shape-aware": the idea is that _ffi
antocuni
commits-noreply at bitbucket.org
Wed Jan 12 14:43:21 CET 2011
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: jitypes2
Changeset: r40628:84badb1fa1e9
Date: 2011-01-12 09:34 +0100
http://bitbucket.org/pypy/pypy/changeset/84badb1fa1e9/
Log: start the refactoring of _ffi to make it "shape-aware": the idea is
that _ffi should be responsible to do the proper conversion between
applevel and interp-level types, but to do so it needs more
knowledge about the "shape": e.g., if the shape indicates a
character, _ffi should expect a 1-lenght app-level string and
convert it properly.
So far, such kind of conversions were done inside _ctypes, which is
now probably broken but will be fixed once the refactoring is
complete
diff --git a/pypy/module/_ffi/test/test__ffi.py b/pypy/module/_ffi/test/test__ffi.py
--- a/pypy/module/_ffi/test/test__ffi.py
+++ b/pypy/module/_ffi/test/test__ffi.py
@@ -69,8 +69,8 @@
def test_simple_types(self):
from _ffi import types
- assert str(types.sint) == '<ffi type sint>'
- assert str(types.uint) == '<ffi type uint>'
+ assert str(types.sint) == "<ffi type sint (shape 'i')>"
+ assert str(types.uint) == "<ffi type uint (shape 'I')>"
def test_callfunc(self):
from _ffi import CDLL, types
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -252,7 +252,7 @@
# term, probably we will move the code for build structures and arrays
# from _rawffi to _ffi
from pypy.module._ffi.interp_ffi import W_FFIType
- return W_FFIType('<name>', self.get_basic_ffi_type())
+ return W_FFIType('<name>', '1', self.get_basic_ffi_type())
def descr_size_alignment(self, space, n=1):
return space.newtuple([space.wrap(self.size * n),
diff --git a/pypy/module/_ffi/interp_ffi.py b/pypy/module/_ffi/interp_ffi.py
--- a/pypy/module/_ffi/interp_ffi.py
+++ b/pypy/module/_ffi/interp_ffi.py
@@ -14,14 +14,45 @@
from pypy.rlib.rarithmetic import intmask, r_uint
class W_FFIType(Wrappable):
- def __init__(self, name, ffitype):
+ def __init__(self, name, shape, ffitype):
self.name = name
+ self.shape = shape
self.ffitype = ffitype
@unwrap_spec('self', ObjSpace)
def str(self, space):
- return space.wrap('<ffi type %s>' % self.name)
+ return space.wrap("<ffi type %s (shape '%s')>" % (self.name, self.shape))
+ def is_signed(self):
+ shape = self.shape
+ return (shape == 'i' or
+ shape == 'l' or
+ shape == 'h' or
+ shape == 'q')
+
+ def is_unsigned(self):
+ shape = self.shape
+ return (shape == 'I' or
+ shape == 'L' or
+ shape == 'H' or
+ shape == 'P' or
+ shape == 'Q')
+
+ def is_longlong(self):
+ shape = self.shape
+ return libffi.IS_32_BIT and (shape == 'q' or shape == 'Q')
+
+ def is_double(self):
+ return self.shape == 'd'
+
+ def is_singlefloat(self):
+ return self.shape == 'f'
+
+ def is_void(self):
+ return self.shape == '0'
+
+ def is_struct(self):
+ return self.shape == '1'
W_FFIType.typedef = TypeDef(
'FFIType',
@@ -34,13 +65,34 @@
def build_ffi_types():
from pypy.rlib.clibffi import FFI_TYPE_P
- tdict = {}
- for key, value in libffi.types.__dict__.iteritems():
- if key == 'getkind' or key == 'is_struct' or key.startswith('__'):
- continue
- assert lltype.typeOf(value) == FFI_TYPE_P
- tdict[key] = W_FFIType(key, value)
- return tdict
+ types = [
+ W_FFIType('sint', 'i', libffi.types.sint),
+ W_FFIType('slong', 'l', libffi.types.slong),
+ W_FFIType('sshort', 'h', libffi.types.sshort),
+ W_FFIType('slonglong', 'q', libffi.types.slonglong),
+ #
+ W_FFIType('uint', 'I', libffi.types.uint),
+ W_FFIType('ulong', 'L', libffi.types.ulong),
+ W_FFIType('ushort', 'H', libffi.types.ushort),
+ W_FFIType('ulonglong', 'Q', libffi.types.ulonglong),
+ #
+ W_FFIType('double', 'd', libffi.types.double),
+ W_FFIType('float', 'f', libffi.types.float),
+ W_FFIType('void', '0', libffi.types.void),
+ W_FFIType('pointer', 'P', libffi.types.pointer),
+
+ # missing types:
+ ## 'c' : ffi_type_uchar,
+ ## 'b' : ffi_type_schar,
+ ## 'B' : ffi_type_uchar,
+ ## 'u' : cast_type_to_ffitype(lltype.UniChar),
+ ## 's' : ffi_type_pointer,
+ ## 'z' : ffi_type_pointer,
+ ## 'O' : ffi_type_pointer,
+ ## 'Z' : ffi_type_pointer,
+
+ ]
+ return dict([(t.name, t) for t in types])
W_types.typedef = TypeDef(
'types',
@@ -59,18 +111,20 @@
class W_FuncPtr(Wrappable):
- _immutable_fields_ = ['func']
+ _immutable_fields_ = ['func', 'argtypes_w[*]', 'w_restype']
- def __init__(self, func):
+ def __init__(self, func, argtypes_w, w_restype):
self.func = func
+ self.argtypes_w = argtypes_w
+ self.w_restype = w_restype
@jit.unroll_safe
- def build_argchain(self, space, argtypes, args_w):
- expected = len(argtypes)
+ def build_argchain(self, space, args_w):
+ expected = len(self.argtypes_w)
given = len(args_w)
if given != expected:
arg = 'arguments'
- if len(argtypes) == 1:
+ if len(self.argtypes_w) == 1:
arg = 'argument'
raise operationerrfmt(space.w_TypeError,
'%s() takes exactly %d %s (%d given)',
@@ -78,27 +132,29 @@
#
argchain = libffi.ArgChain()
for i in range(expected):
- argtype = argtypes[i]
+ w_argtype = self.argtypes_w[i]
w_arg = args_w[i]
- kind = libffi.types.getkind(argtype)
- if kind == 'i':
+ if w_argtype.is_longlong():
+ # note that we must check for longlong first, because either
+ # is_signed or is_unsigned returns true anyway
+ assert libffi.IS_32_BIT
+ kind = libffi.types.getkind(w_argtype.ffitype) # XXX: remove the kind
+ self.arg_longlong(space, argchain, kind, w_arg)
+ elif w_argtype.is_signed():
argchain.arg(space.int_w(w_arg))
- elif kind == 'u':
+ elif w_argtype.is_unsigned():
argchain.arg(intmask(space.uint_w(w_arg)))
- elif kind == 'f':
+ elif w_argtype.is_double():
argchain.arg(space.float_w(w_arg))
- elif kind == 'S': # struct
+ elif w_argtype.is_singlefloat():
+ argchain.arg_singlefloat(space.float_w(w_arg))
+ elif w_argtype.is_struct():
# arg_raw directly takes value to put inside ll_args
uintval = space.uint_w(w_arg)
ptrval = rffi.cast(rffi.VOIDP, uintval)
argchain.arg_raw(ptrval)
- elif kind == 's':
- argchain.arg_singlefloat(space.float_w(w_arg))
- elif kind == 'I' or kind == 'U':
- assert libffi.IS_32_BIT
- self.arg_longlong(space, argchain, kind, w_arg)
else:
- assert False, "Argument kind '%s' not supported" % kind
+ assert False, "Argument shape '%s' not supported" % w_argtype.shape
return argchain
@jit.dont_look_inside
@@ -119,30 +175,34 @@
@unwrap_spec('self', ObjSpace, 'args_w')
def call(self, space, args_w):
self = jit.hint(self, promote=True)
- argchain = self.build_argchain(space, self.func.argtypes, args_w)
- reskind = libffi.types.getkind(self.func.restype)
- if reskind == 'i':
+ argchain = self.build_argchain(space, args_w)
+ w_restype = self.w_restype
+ if w_restype.is_longlong():
+ # note that we must check for longlong first, because either
+ # is_signed or is_unsigned returns true anyway
+ assert libffi.IS_32_BIT
+ reskind = libffi.types.getkind(self.func.restype) # XXX: remove the kind
+ return self._call_longlong(space, argchain, reskind)
+ elif w_restype.is_signed():
return self._call_int(space, argchain)
- elif reskind == 'u':
+ elif w_restype.is_unsigned():
return self._call_uint(space, argchain)
- elif reskind == 'f':
+ elif w_restype.is_double():
floatres = self.func.call(argchain, rffi.DOUBLE)
return space.wrap(floatres)
- elif reskind == 's':
+ elif w_restype.is_singlefloat():
# the result is a float, but widened to be inside a double
floatres = self.func.call(argchain, rffi.FLOAT)
return space.wrap(floatres)
- elif reskind == 'I' or reskind == 'U':
- assert libffi.IS_32_BIT
- return self._call_longlong(space, argchain, reskind)
- elif reskind == 'S':
+ elif w_restype.is_struct():
# we return the address of the buffer as an integer
return self._call_uint(space, argchain)
- else:
- assert reskind == 'v'
+ elif w_restype.is_void():
voidres = self.func.call(argchain, lltype.Void)
assert voidres is None
return space.w_None
+ else:
+ assert False, "Return value shape '%s' not supported" % w_restype.shape
def _call_int(self, space, argchain):
# if the declared return type of the function is smaller than LONG,
@@ -227,13 +287,14 @@
@unwrap_spec(ObjSpace, W_Root, r_uint, str, W_Root, W_Root)
def descr_fromaddr(space, w_cls, addr, name, w_argtypes, w_restype):
+ argtypes_w = space.listview(w_argtypes) # XXX: fix annotation
argtypes = [unwrap_ffitype(space, w_argtype) for w_argtype in
- space.listview(w_argtypes)]
+ argtypes_w]
restype = unwrap_ffitype(space, w_restype, allow_void=True)
addr = rffi.cast(rffi.VOIDP, addr)
func = libffi.Func(name, argtypes, restype, addr)
- return W_FuncPtr(func)
-
+ return W_FuncPtr(func, argtypes_w, w_restype)
+
W_FuncPtr.typedef = TypeDef(
'_ffi.FuncPtr',
@@ -258,8 +319,9 @@
@unwrap_spec('self', ObjSpace, str, W_Root, W_Root)
def getfunc(self, space, name, w_argtypes, w_restype):
+ argtypes_w = space.listview(w_argtypes) # XXX: fix annotation
argtypes = [unwrap_ffitype(space, w_argtype) for w_argtype in
- space.listview(w_argtypes)]
+ argtypes_w]
restype = unwrap_ffitype(space, w_restype, allow_void=True)
try:
func = self.cdll.getpointer(name, argtypes, restype)
@@ -267,7 +329,7 @@
raise operationerrfmt(space.w_AttributeError,
"No symbol %s found in library %s", name, self.name)
- return W_FuncPtr(func)
+ return W_FuncPtr(func, argtypes_w, w_restype)
@unwrap_spec('self', ObjSpace, str)
def getaddressindll(self, space, name):
More information about the Pypy-commit
mailing list