[pypy-commit] pypy ffi-backend: Remove this version of libffi.py.

arigo noreply at buildbot.pypy.org
Thu Aug 2 22:42:01 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: ffi-backend
Changeset: r56544:4f436a389717
Date: 2012-08-02 13:33 +0200
http://bitbucket.org/pypy/pypy/changeset/4f436a389717/

Log:	Remove this version of libffi.py.

diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
deleted file mode 100644
--- a/pypy/rlib/libffi.py
+++ /dev/null
@@ -1,434 +0,0 @@
-from __future__ import with_statement
-
-from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.rlib.objectmodel import specialize, enforceargs
-from pypy.rlib.rarithmetic import intmask, r_uint, r_singlefloat, r_longlong
-from pypy.rlib import jit
-from pypy.rlib import clibffi
-from pypy.rlib.clibffi import FUNCFLAG_CDECL, FUNCFLAG_STDCALL, \
-        AbstractFuncPtr, push_arg_as_ffiptr, c_ffi_call, FFI_TYPE_STRUCT
-from pypy.rlib.rdynload import dlopen, dlclose, dlsym, dlsym_byordinal
-from pypy.rlib.rdynload import DLLHANDLE
-
-import os
-
-class types(object):
-    """
-    This namespace contains the primitive types you can use to declare the
-    signatures of the ffi functions.
-
-    In general, the name of the types are closely related to the ones of the
-    C-level ffi_type_*: e.g, instead of ffi_type_sint you should use
-    libffi.types.sint.
-
-    However, you should not rely on a perfect correspondence: in particular,
-    the exact meaning of ffi_type_{slong,ulong} changes a lot between libffi
-    versions, so types.slong could be different than ffi_type_slong.
-    """
-
-    @classmethod
-    def _import(cls):
-        prefix = 'ffi_type_'
-        for key, value in clibffi.__dict__.iteritems():
-            if key.startswith(prefix):
-                name = key[len(prefix):]
-                setattr(cls, name, value)
-        cls.slong = clibffi.cast_type_to_ffitype(rffi.LONG)
-        cls.ulong = clibffi.cast_type_to_ffitype(rffi.ULONG)
-        cls.slonglong = clibffi.cast_type_to_ffitype(rffi.LONGLONG)
-        cls.ulonglong = clibffi.cast_type_to_ffitype(rffi.ULONGLONG)
-        cls.signed = clibffi.cast_type_to_ffitype(rffi.SIGNED)
-        cls.wchar_t = clibffi.cast_type_to_ffitype(lltype.UniChar)
-        del cls._import
-
-    @staticmethod
-    @jit.elidable
-    def getkind(ffi_type):
-        """Returns 'v' for void, 'f' for float, 'i' for signed integer,
-        and 'u' for unsigned integer.
-        """
-        if   ffi_type is types.void:    return 'v'
-        elif ffi_type is types.double:  return 'f'
-        elif ffi_type is types.float:   return 's'
-        elif ffi_type is types.pointer: return 'u'
-        #
-        elif ffi_type is types.schar:   return 'i'
-        elif ffi_type is types.uchar:   return 'u'
-        elif ffi_type is types.sshort:  return 'i'
-        elif ffi_type is types.ushort:  return 'u'
-        elif ffi_type is types.sint:    return 'i'
-        elif ffi_type is types.uint:    return 'u'
-        elif ffi_type is types.slong:   return 'i'
-        elif ffi_type is types.ulong:   return 'u'
-        #
-        elif ffi_type is types.sint8:   return 'i'
-        elif ffi_type is types.uint8:   return 'u'
-        elif ffi_type is types.sint16:  return 'i'
-        elif ffi_type is types.uint16:  return 'u'
-        elif ffi_type is types.sint32:  return 'i'
-        elif ffi_type is types.uint32:  return 'u'
-        ## (note that on 64-bit platforms, types.sint64 is types.slong and the
-        ## case is caught above)
-        elif ffi_type is types.sint64:  return 'I'
-        elif ffi_type is types.uint64:  return 'U'
-        #
-        elif types.is_struct(ffi_type): return 'S'
-        raise KeyError
-
-    @staticmethod
-    @jit.elidable
-    def is_struct(ffi_type):
-        return intmask(ffi_type.c_type) == FFI_TYPE_STRUCT
-
-types._import()
-
-# this was '_fits_into_long', which is not adequate, because long is
-# not necessary the type where we compute with. Actually meant is
-# the type 'Signed'.
-
- at specialize.arg(0)
-def _fits_into_signed(TYPE):
-    if isinstance(TYPE, lltype.Ptr):
-        return True # pointers always fits into Signeds
-    if not isinstance(TYPE, lltype.Primitive):
-        return False
-    if TYPE is lltype.Void or TYPE is rffi.FLOAT or TYPE is rffi.DOUBLE:
-        return False
-    sz = rffi.sizeof(TYPE)
-    return sz <= rffi.sizeof(rffi.SIGNED)
-
-
-# ======================================================================
-
-IS_32_BIT = (r_uint.BITS == 32)
-
- at specialize.memo()
-def _check_type(TYPE):
-    if isinstance(TYPE, lltype.Ptr):
-        if TYPE.TO._gckind != 'raw':
-            raise TypeError, "Can only push raw values to C, not 'gc'"
-        # XXX probably we should recursively check for struct fields here,
-        # lets just ignore that for now
-        if isinstance(TYPE.TO, lltype.Array) and 'nolength' not in TYPE.TO._hints:
-            raise TypeError, "Can only push to C arrays without length info"
-
-
-class ArgChain(object):
-    first = None
-    last = None
-    numargs = 0
-
-    @specialize.argtype(1)
-    def arg(self, val):
-        TYPE = lltype.typeOf(val)
-        _check_type(TYPE)
-        if _fits_into_signed(TYPE):
-            cls = IntArg
-            val = rffi.cast(rffi.SIGNED, val)
-        elif TYPE is rffi.DOUBLE:
-            cls = FloatArg
-        elif TYPE is rffi.LONGLONG or TYPE is rffi.ULONGLONG:
-            cls = LongLongArg
-            val = rffi.cast(rffi.LONGLONG, val)
-        elif TYPE is rffi.FLOAT:
-            cls = SingleFloatArg
-        else:
-            raise TypeError, 'Unsupported argument type: %s' % TYPE
-        self._append(cls(val))
-        return self
-
-    def arg_raw(self, val):
-        self._append(RawArg(val))
-
-    def _append(self, arg):
-        if self.first is None:
-            self.first = self.last = arg
-        else:
-            self.last.next = arg
-            self.last = arg
-        self.numargs += 1
-
-
-class AbstractArg(object):
-    next = None
-
-class IntArg(AbstractArg):
-    """ An argument holding an integer
-    """
-
-    def __init__(self, intval):
-        self.intval = intval
-
-    def push(self, func, ll_args, i):
-        func._push_int(self.intval, ll_args, i)
-
-
-class FloatArg(AbstractArg):
-    """ An argument holding a python float (i.e. a C double)
-    """
-
-    def __init__(self, floatval):
-        self.floatval = floatval
-
-    def push(self, func, ll_args, i):
-        func._push_float(self.floatval, ll_args, i)
-
-class RawArg(AbstractArg):
-    """ An argument holding a raw pointer to put inside ll_args
-    """
-
-    def __init__(self, ptrval):
-        self.ptrval = ptrval
-
-    def push(self, func, ll_args, i):
-        func._push_raw(self.ptrval, ll_args, i)
-
-class SingleFloatArg(AbstractArg):
-    """ An argument representing a C float
-    """
-
-    def __init__(self, singlefloatval):
-        self.singlefloatval = singlefloatval
-
-    def push(self, func, ll_args, i):
-        func._push_singlefloat(self.singlefloatval, ll_args, i)
-
-
-class LongLongArg(AbstractArg):
-    """ An argument representing a C long long
-    """
-
-    def __init__(self, longlongval):
-        self.longlongval = longlongval
-
-    def push(self, func, ll_args, i):
-        func._push_longlong(self.longlongval, ll_args, i)
-
-
-# ======================================================================
-
-
-class Func(AbstractFuncPtr):
-
-    _immutable_fields_ = ['funcsym']
-    argtypes = []
-    restype = clibffi.FFI_TYPE_NULL
-    flags = 0
-    funcsym = lltype.nullptr(rffi.VOIDP.TO)
-
-    def __init__(self, name, argtypes, restype, funcsym, flags=FUNCFLAG_CDECL,
-                 keepalive=None):
-        AbstractFuncPtr.__init__(self, name, argtypes, restype, flags)
-        self.keepalive = keepalive
-        self.funcsym = funcsym
-
-    # ========================================================================
-    # PUBLIC INTERFACE
-    # ========================================================================
-
-    @jit.unroll_safe
-    @specialize.arg(2, 3)
-    def call(self, argchain, RESULT, is_struct=False):
-        # WARNING!  This code is written carefully in a way that the JIT
-        # optimizer will see a sequence of calls like the following:
-        #
-        #    libffi_prepare_call
-        #    libffi_push_arg
-        #    libffi_push_arg
-        #    ...
-        #    libffi_call
-        #
-        # It is important that there is no other operation in the middle, else
-        # the optimizer will fail to recognize the pattern and won't turn it
-        # into a fast CALL.  Note that "arg = arg.next" is optimized away,
-        # assuming that argchain is completely virtual.
-        self = jit.promote(self)
-        if argchain.numargs != len(self.argtypes):
-            raise TypeError, 'Wrong number of arguments: %d expected, got %d' %\
-                (len(self.argtypes), argchain.numargs)
-        ll_args = self._prepare()
-        i = 0
-        arg = argchain.first
-        while arg:
-            arg.push(self, ll_args, i)
-            i += 1
-            arg = arg.next
-        #
-        if is_struct:
-            assert types.is_struct(self.restype)
-            res = self._do_call_raw(self.funcsym, ll_args)
-        elif _fits_into_signed(RESULT):
-            assert not types.is_struct(self.restype)
-            res = self._do_call_int(self.funcsym, ll_args)
-        elif RESULT is rffi.DOUBLE:
-            return self._do_call_float(self.funcsym, ll_args)
-        elif RESULT is rffi.FLOAT:
-            return self._do_call_singlefloat(self.funcsym, ll_args)
-        elif RESULT is rffi.LONGLONG or RESULT is rffi.ULONGLONG:
-            assert IS_32_BIT
-            res = self._do_call_longlong(self.funcsym, ll_args)
-        elif RESULT is lltype.Void:
-            return self._do_call_void(self.funcsym, ll_args)
-        else:
-            raise TypeError, 'Unsupported result type: %s' % RESULT
-        #
-        return rffi.cast(RESULT, res)
-
-    # END OF THE PUBLIC INTERFACE
-    # ------------------------------------------------------------------------
-
-    # JIT friendly interface
-    # the following methods are supposed to be seen opaquely by the optimizer
-
-    @jit.oopspec('libffi_prepare_call(self)')
-    def _prepare(self):
-        ll_args = lltype.malloc(rffi.VOIDPP.TO, len(self.argtypes), flavor='raw')
-        return ll_args
-
-
-    # _push_* and _do_call_* in theory could be automatically specialize()d by
-    # the annotator.  However, specialization doesn't work well with oopspec,
-    # so we specialize them by hand
-
-    @jit.oopspec('libffi_push_int(self, value, ll_args, i)')
-    @enforceargs( None, int,   None,    int) # fix the annotation for tests
-    def _push_int(self, value, ll_args, i):
-        self._push_arg(value, ll_args, i)
-
-    @jit.dont_look_inside
-    def _push_raw(self, value, ll_args, i):
-        ll_args[i] = value
-
-    @jit.oopspec('libffi_push_float(self, value, ll_args, i)')
-    @enforceargs(   None, float, None,    int) # fix the annotation for tests
-    def _push_float(self, value, ll_args, i):
-        self._push_arg(value, ll_args, i)
-
-    @jit.oopspec('libffi_push_singlefloat(self, value, ll_args, i)')
-    @enforceargs(None, r_singlefloat, None, int) # fix the annotation for tests
-    def _push_singlefloat(self, value, ll_args, i):
-        self._push_arg(value, ll_args, i)
-
-    @jit.oopspec('libffi_push_longlong(self, value, ll_args, i)')
-    @enforceargs(None, r_longlong, None, int) # fix the annotation for tests
-    def _push_longlong(self, value, ll_args, i):
-        self._push_arg(value, ll_args, i)
-
-    @jit.oopspec('libffi_call_int(self, funcsym, ll_args)')
-    def _do_call_int(self, funcsym, ll_args):
-        return self._do_call(funcsym, ll_args, rffi.SIGNED)
-
-    @jit.oopspec('libffi_call_float(self, funcsym, ll_args)')
-    def _do_call_float(self, funcsym, ll_args):
-        return self._do_call(funcsym, ll_args, rffi.DOUBLE)
-
-    @jit.oopspec('libffi_call_singlefloat(self, funcsym, ll_args)')
-    def _do_call_singlefloat(self, funcsym, ll_args):
-        return self._do_call(funcsym, ll_args, rffi.FLOAT)
-
-    @jit.dont_look_inside
-    def _do_call_raw(self, funcsym, ll_args):
-        # same as _do_call_int, but marked as jit.dont_look_inside
-        return self._do_call(funcsym, ll_args, rffi.SIGNED)
-
-    @jit.oopspec('libffi_call_longlong(self, funcsym, ll_args)')
-    def _do_call_longlong(self, funcsym, ll_args):
-        return self._do_call(funcsym, ll_args, rffi.LONGLONG)
-
-    @jit.oopspec('libffi_call_void(self, funcsym, ll_args)')
-    def _do_call_void(self, funcsym, ll_args):
-        return self._do_call(funcsym, ll_args, lltype.Void)
-
-    # ------------------------------------------------------------------------
-    # private methods
-
-    @specialize.argtype(1)
-    def _push_arg(self, value, ll_args, i):
-        # XXX: check the type is not translated?
-        argtype = self.argtypes[i]
-        c_size = intmask(argtype.c_size)
-        ll_buf = lltype.malloc(rffi.CCHARP.TO, c_size, flavor='raw')
-        push_arg_as_ffiptr(argtype, value, ll_buf)
-        ll_args[i] = ll_buf
-
-    @specialize.arg(3)
-    def _do_call(self, funcsym, ll_args, RESULT):
-        # XXX: check len(args)?
-        ll_result = lltype.nullptr(rffi.CCHARP.TO)
-        if self.restype != types.void:
-            ll_result = lltype.malloc(rffi.CCHARP.TO,
-                                      intmask(self.restype.c_size),
-                                      flavor='raw')
-        ffires = c_ffi_call(self.ll_cif,
-                            self.funcsym,
-                            rffi.cast(rffi.VOIDP, ll_result),
-                            rffi.cast(rffi.VOIDPP, ll_args))
-        if RESULT is not lltype.Void:
-            TP = lltype.Ptr(rffi.CArray(RESULT))
-            buf = rffi.cast(TP, ll_result)
-            if types.is_struct(self.restype):
-                assert RESULT == rffi.SIGNED
-                # for structs, we directly return the buffer and transfer the
-                # ownership
-                res = rffi.cast(RESULT, buf)
-            else:
-                res = buf[0]
-        else:
-            res = None
-        self._free_buffers(ll_result, ll_args)
-        clibffi.check_fficall_result(ffires, self.flags)
-        return res
-
-    def _free_buffers(self, ll_result, ll_args):
-        if ll_result:
-            self._free_buffer_maybe(rffi.cast(rffi.VOIDP, ll_result), self.restype)
-        for i in range(len(self.argtypes)):
-            argtype = self.argtypes[i]
-            self._free_buffer_maybe(ll_args[i], argtype)
-        lltype.free(ll_args, flavor='raw')
-
-    def _free_buffer_maybe(self, buf, ffitype):
-        # if it's a struct, the buffer is not freed and the ownership is
-        # already of the caller (in case of ll_args buffers) or transferred to
-        # it (in case of ll_result buffer)
-        if not types.is_struct(ffitype):
-            lltype.free(buf, flavor='raw')
-
-
-# ======================================================================
-
-
-# XXX: it partially duplicate the code in clibffi.py
-class CDLL(object):
-    def __init__(self, libname, mode=-1):
-        """Load the library, or raises DLOpenError."""
-        self.lib = rffi.cast(DLLHANDLE, 0)
-        with rffi.scoped_str2charp(libname) as ll_libname:
-            self.lib = dlopen(ll_libname, mode)
-
-    def __del__(self):
-        if self.lib:
-            dlclose(self.lib)
-            self.lib = rffi.cast(DLLHANDLE, 0)
-
-    def getpointer(self, name, argtypes, restype, flags=FUNCFLAG_CDECL):
-        return Func(name, argtypes, restype, dlsym(self.lib, name),
-                    flags=flags, keepalive=self)
-
-    def getpointer_by_ordinal(self, name, argtypes, restype,
-                              flags=FUNCFLAG_CDECL):
-        return Func('by_ordinal', argtypes, restype, 
-                    dlsym_byordinal(self.lib, name),
-                    flags=flags, keepalive=self)
-    def getaddressindll(self, name):
-        return dlsym(self.lib, name)
-
-if os.name == 'nt':
-    class WinDLL(CDLL):
-        def getpointer(self, name, argtypes, restype, flags=FUNCFLAG_STDCALL):
-            return Func(name, argtypes, restype, dlsym(self.lib, name),
-                        flags=flags, keepalive=self)
-        def getpointer_by_ordinal(self, name, argtypes, restype,
-                                  flags=FUNCFLAG_STDCALL):
-            return Func(name, argtypes, restype, dlsym_byordinal(self.lib, name),
-                        flags=flags, keepalive=self)
diff --git a/pypy/rlib/test/test_libffi.py b/pypy/rlib/test/test_libffi.py
deleted file mode 100644
--- a/pypy/rlib/test/test_libffi.py
+++ /dev/null
@@ -1,610 +0,0 @@
-import os
-
-import py
-
-from pypy.rlib.rarithmetic import r_singlefloat, r_longlong, r_ulonglong
-from pypy.rlib.test.test_clibffi import BaseFfiTest, make_struct_ffitype_e
-from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED
-from pypy.rpython.llinterp import LLException
-from pypy.rlib.libffi import (CDLL, ArgChain, types,
-                              IS_32_BIT, array_getitem, array_setitem)
-from pypy.rlib.libffi import (struct_getfield_int, struct_setfield_int,
-                              struct_getfield_longlong, struct_setfield_longlong,
-                              struct_getfield_float, struct_setfield_float,
-                              struct_getfield_singlefloat, struct_setfield_singlefloat)
-
-class TestLibffiMisc(BaseFfiTest):
-
-    CDLL = CDLL
-
-    def test_argchain(self):
-        chain = ArgChain()
-        assert chain.numargs == 0
-        chain2 = chain.arg(42)
-        assert chain2 is chain
-        assert chain.numargs == 1
-        intarg = chain.first
-        assert chain.last is intarg
-        assert intarg.intval == 42
-        chain.arg(123.45)
-        assert chain.numargs == 2
-        assert chain.first is intarg
-        assert intarg.next is chain.last
-        floatarg = intarg.next
-        assert floatarg.floatval == 123.45
-
-    def test_wrong_args(self):
-        # so far the test passes but for the wrong reason :-), i.e. because
-        # .arg() only supports integers and floats
-        chain = ArgChain()
-        x = lltype.malloc(lltype.GcStruct('xxx'))
-        y = lltype.malloc(lltype.GcArray(rffi.SIGNED), 3)
-        z = lltype.malloc(lltype.Array(rffi.SIGNED), 4, flavor='raw')
-        py.test.raises(TypeError, "chain.arg(x)")
-        py.test.raises(TypeError, "chain.arg(y)")
-        py.test.raises(TypeError, "chain.arg(z)")
-        lltype.free(z, flavor='raw')
-
-    def test_library_open(self):
-        lib = self.get_libc()
-        del lib
-        assert not ALLOCATED
-
-    def test_library_get_func(self):
-        lib = self.get_libc()
-        ptr = lib.getpointer('fopen', [], types.void)
-        py.test.raises(KeyError, lib.getpointer, 'xxxxxxxxxxxxxxx', [], types.void)
-        del ptr
-        del lib
-        assert not ALLOCATED
-
-    def test_struct_fields(self):
-        longsize = 4 if IS_32_BIT else 8
-        POINT = lltype.Struct('POINT',
-                              ('x', rffi.LONG),
-                              ('y', rffi.SHORT),
-                              ('z', rffi.VOIDP),
-                              )
-        y_ofs = longsize
-        z_ofs = longsize*2
-        p = lltype.malloc(POINT, flavor='raw')
-        p.x = 42
-        p.y = rffi.cast(rffi.SHORT, -1)
-        p.z = rffi.cast(rffi.VOIDP, 0x1234)
-        addr = rffi.cast(rffi.VOIDP, p)
-        assert struct_getfield_int(types.slong, addr, 0) == 42
-        assert struct_getfield_int(types.sshort, addr, y_ofs) == -1
-        assert struct_getfield_int(types.pointer, addr, z_ofs) == 0x1234
-        #
-        struct_setfield_int(types.slong, addr, 0, 43)
-        struct_setfield_int(types.sshort, addr, y_ofs, 0x1234FFFE) # 0x1234 is masked out
-        struct_setfield_int(types.pointer, addr, z_ofs, 0x4321)
-        assert p.x == 43
-        assert p.y == -2
-        assert rffi.cast(rffi.LONG, p.z) == 0x4321
-        #
-        lltype.free(p, flavor='raw')
-
-    def test_array_fields(self):
-        POINT = lltype.Struct("POINT",
-            ("x", lltype.Float),
-            ("y", lltype.Float),
-        )
-        points = lltype.malloc(rffi.CArray(POINT), 2, flavor="raw")
-        points[0].x = 1.0
-        points[0].y = 2.0
-        points[1].x = 3.0
-        points[1].y = 4.0
-        points = rffi.cast(rffi.CArrayPtr(lltype.Char), points)
-        assert array_getitem(types.double, 16, points, 0, 0) == 1.0
-        assert array_getitem(types.double, 16, points, 0, 8) == 2.0
-        assert array_getitem(types.double, 16, points, 1, 0) == 3.0
-        assert array_getitem(types.double, 16, points, 1, 8) == 4.0
-        #
-        array_setitem(types.double, 16, points, 0, 0, 10.0)
-        array_setitem(types.double, 16, points, 0, 8, 20.0)
-        array_setitem(types.double, 16, points, 1, 0, 30.0)
-        array_setitem(types.double, 16, points, 1, 8, 40.0)
-        #
-        assert array_getitem(types.double, 16, points, 0, 0) == 10.0
-        assert array_getitem(types.double, 16, points, 0, 8) == 20.0
-        assert array_getitem(types.double, 16, points, 1, 0) == 30.0
-        assert array_getitem(types.double, 16, points, 1, 8) == 40.0
-        #
-        lltype.free(points, flavor="raw")
-
-
-    def test_struct_fields_longlong(self):
-        POINT = lltype.Struct('POINT',
-                              ('x', rffi.LONGLONG),
-                              ('y', rffi.ULONGLONG)
-                              )
-        y_ofs = 8
-        p = lltype.malloc(POINT, flavor='raw')
-        p.x = r_longlong(123)
-        p.y = r_ulonglong(456)
-        addr = rffi.cast(rffi.VOIDP, p)
-        assert struct_getfield_longlong(types.slonglong, addr, 0) == 123
-        assert struct_getfield_longlong(types.ulonglong, addr, y_ofs) == 456
-        #
-        v = rffi.cast(lltype.SignedLongLong, r_ulonglong(9223372036854775808))
-        struct_setfield_longlong(types.slonglong, addr, 0, v)
-        struct_setfield_longlong(types.ulonglong, addr, y_ofs, r_longlong(-1))
-        assert p.x == -9223372036854775808
-        assert rffi.cast(lltype.UnsignedLongLong, p.y) == 18446744073709551615
-        #
-        lltype.free(p, flavor='raw')
-
-    def test_struct_fields_float(self):
-        POINT = lltype.Struct('POINT',
-                              ('x', rffi.DOUBLE),
-                              ('y', rffi.DOUBLE)
-                              )
-        y_ofs = 8
-        p = lltype.malloc(POINT, flavor='raw')
-        p.x = 123.4
-        p.y = 567.8
-        addr = rffi.cast(rffi.VOIDP, p)
-        assert struct_getfield_float(types.double, addr, 0) == 123.4
-        assert struct_getfield_float(types.double, addr, y_ofs) == 567.8
-        #
-        struct_setfield_float(types.double, addr, 0, 321.0)
-        struct_setfield_float(types.double, addr, y_ofs, 876.5)
-        assert p.x == 321.0
-        assert p.y == 876.5
-        #
-        lltype.free(p, flavor='raw')
-
-    def test_struct_fields_singlefloat(self):
-        POINT = lltype.Struct('POINT',
-                              ('x', rffi.FLOAT),
-                              ('y', rffi.FLOAT)
-                              )
-        y_ofs = 4
-        p = lltype.malloc(POINT, flavor='raw')
-        p.x = r_singlefloat(123.4)
-        p.y = r_singlefloat(567.8)
-        addr = rffi.cast(rffi.VOIDP, p)
-        assert struct_getfield_singlefloat(types.double, addr, 0) == r_singlefloat(123.4)
-        assert struct_getfield_singlefloat(types.double, addr, y_ofs) == r_singlefloat(567.8)
-        #
-        struct_setfield_singlefloat(types.double, addr, 0, r_singlefloat(321.0))
-        struct_setfield_singlefloat(types.double, addr, y_ofs, r_singlefloat(876.5))
-        assert p.x == r_singlefloat(321.0)
-        assert p.y == r_singlefloat(876.5)
-        #
-        lltype.free(p, flavor='raw')
-
-    def test_windll(self):
-        if os.name != 'nt':
-            skip('Run only on windows')
-        from pypy.rlib.libffi import WinDLL
-        dll = WinDLL('Kernel32.dll')
-        sleep = dll.getpointer('Sleep',[types.uint], types.void)
-        chain = ArgChain()
-        chain.arg(10)
-        sleep.call(chain, lltype.Void, is_struct=False)
-
-class TestLibffiCall(BaseFfiTest):
-    """
-    Test various kind of calls through libffi.
-
-    The peculiarity of these tests is that they are run both directly (going
-    really through libffi) and by jit/metainterp/test/test_fficall.py, which
-    tests the call when JITted.
-
-    If you need to test a behaviour than it's not affected by JITing (e.g.,
-    typechecking), you should put your test in TestLibffiMisc.
-    """
-
-    CDLL = CDLL
-
-    @classmethod
-    def setup_class(cls):
-        from pypy.tool.udir import udir
-        from pypy.translator.tool.cbuild import ExternalCompilationInfo
-        from pypy.translator.tool.cbuild import STANDARD_DEFINES
-        from pypy.translator.platform import platform
-
-        BaseFfiTest.setup_class()
-        # prepare C code as an example, so we can load it and call
-        # it via rlib.libffi
-        c_file = udir.ensure("test_libffi", dir=1).join("foolib.c")
-        # automatically collect the C source from the docstrings of the tests
-        snippets = []
-        exports = []
-        for name in dir(cls):
-            if name.startswith('test_'):
-                meth = getattr(cls, name)
-                # the heuristic to determine it it's really C code could be
-                # improved: so far we just check that there is a '{' :-)
-                if meth.__doc__ is not None and '{' in meth.__doc__:
-                    snippets.append(meth.__doc__)
-                    import re
-                    for match in re.finditer(" ([A-Za-z_]+)\(", meth.__doc__):
-                        exports.append(match.group(1))
-        #
-        c_file.write(STANDARD_DEFINES + str(py.code.Source('\n'.join(snippets))))
-        eci = ExternalCompilationInfo(export_symbols=exports)
-        cls.libfoo_name = str(platform.compile([c_file], eci, 'x',
-                                               standalone=False))
-        cls.dll = cls.CDLL(cls.libfoo_name)
-
-    def teardown_class(cls):
-        if cls.dll:
-            cls.dll.__del__()
-            # Why doesn't this call cls.dll.__del__() ?
-            #del cls.dll
-
-    def get_libfoo(self):
-        return self.dll    
-
-    def call(self, funcspec, args, RESULT, is_struct=False, jitif=[]):
-        """
-        Call the specified function after constructing and ArgChain with the
-        arguments in ``args``.
-
-        The function is specified with ``funcspec``, which is a tuple of the
-        form (lib, name, argtypes, restype).
-
-        This method is overridden by metainterp/test/test_fficall.py in
-        order to do the call in a loop and JIT it. The optional arguments are
-        used only by that overridden method.
-
-        """
-        lib, name, argtypes, restype = funcspec
-        func = lib.getpointer(name, argtypes, restype)
-        chain = ArgChain()
-        for arg in args:
-            if isinstance(arg, tuple):
-                methname, arg = arg
-                meth = getattr(chain, methname)
-                meth(arg)
-            else:
-                chain.arg(arg)
-        return func.call(chain, RESULT, is_struct=is_struct)
-
-    # ------------------------------------------------------------------------
-
-    def test_very_simple(self):
-        """
-            int diff_xy(int x, Signed y)
-            {
-                return x - y;
-            }
-        """
-        libfoo = self.get_libfoo()
-        func = (libfoo, 'diff_xy', [types.sint, types.signed], types.sint)
-        res = self.call(func, [50, 8], lltype.Signed)
-        assert res == 42
-
-    def test_simple(self):
-        """
-            int sum_xy(int x, double y)
-            {
-                return (x + (int)y);
-            }
-        """
-        libfoo = self.get_libfoo()
-        func = (libfoo, 'sum_xy', [types.sint, types.double], types.sint)
-        res = self.call(func, [38, 4.2], lltype.Signed, jitif=["floats"])
-        assert res == 42
-
-    def test_float_result(self):
-        libm = self.get_libm()
-        func = (libm, 'pow', [types.double, types.double], types.double)
-        res = self.call(func, [2.0, 3.0], rffi.DOUBLE, jitif=["floats"])
-        assert res == 8.0
-
-    def test_cast_result(self):
-        """
-            unsigned char cast_to_uchar_and_ovf(int x)
-            {
-                return 200+(unsigned char)x;
-            }
-        """
-        libfoo = self.get_libfoo()
-        func = (libfoo, 'cast_to_uchar_and_ovf', [types.sint], types.uchar)
-        res = self.call(func, [0], rffi.UCHAR)
-        assert res == 200
-
-    def test_cast_argument(self):
-        """
-            int many_args(char a, int b)
-            {
-                return a+b;
-            }
-        """
-        libfoo = self.get_libfoo()
-        func = (libfoo, 'many_args', [types.uchar, types.sint], types.sint)
-        res = self.call(func, [chr(20), 22], rffi.SIGNED)
-        assert res == 42
-
-    def test_char_args(self):
-        """
-        char sum_args(char a, char b) {
-            return a + b;
-        }
-        """
-        libfoo = self.get_libfoo()
-        func = (libfoo, 'sum_args', [types.schar, types.schar], types.schar)
-        res = self.call(func, [123, 43], rffi.CHAR)
-        assert res == chr(166)
-
-    def test_unsigned_short_args(self):
-        """
-            unsigned short sum_xy_us(unsigned short x, unsigned short y)
-            {
-                return x+y;
-            }
-        """
-        libfoo = self.get_libfoo()
-        func = (libfoo, 'sum_xy_us', [types.ushort, types.ushort], types.ushort)
-        res = self.call(func, [32000, 8000], rffi.USHORT)
-        assert res == 40000
-
-
-    def test_pointer_as_argument(self):
-        """#include <stdlib.h>
-            Signed inc(Signed* x)
-            {
-                Signed oldval;
-                if (x == NULL)
-                    return -1;
-                oldval = *x;
-                *x = oldval+1;
-                return oldval;
-            }
-        """
-        libfoo = self.get_libfoo()
-        func = (libfoo, 'inc', [types.pointer], types.signed)
-        null = lltype.nullptr(rffi.SIGNEDP.TO)
-        res = self.call(func, [null], rffi.SIGNED)
-        assert res == -1
-        #
-        ptr_result = lltype.malloc(rffi.SIGNEDP.TO, 1, flavor='raw')
-        ptr_result[0] = 41
-        res = self.call(func, [ptr_result], rffi.SIGNED)
-        if self.__class__ is TestLibffiCall:
-            # the function was called only once
-            assert res == 41
-            assert ptr_result[0] == 42
-            lltype.free(ptr_result, flavor='raw')
-            # the test does not make sense when run with the JIT through
-            # meta_interp, because the __del__ are not properly called (hence
-            # we "leak" memory)
-            del libfoo
-            assert not ALLOCATED
-        else:
-            # the function as been called 9 times
-            assert res == 50
-            assert ptr_result[0] == 51
-            lltype.free(ptr_result, flavor='raw')
-
-    def test_return_pointer(self):
-        """
-            struct pair {
-                Signed a;
-                Signed b;
-            };
-
-            struct pair my_static_pair = {10, 20};
-
-            Signed* get_pointer_to_b()
-            {
-                return &my_static_pair.b;
-            }
-        """
-        libfoo = self.get_libfoo()
-        func = (libfoo, 'get_pointer_to_b', [], types.pointer)
-        res = self.call(func, [], rffi.SIGNEDP)
-        assert res[0] == 20
-
-    def test_void_result(self):
-        """
-            int dummy;
-            void set_dummy(int val) { dummy = val; }
-            int get_dummy() { return dummy; }
-        """
-        libfoo = self.get_libfoo()
-        set_dummy = (libfoo, 'set_dummy', [types.sint], types.void)
-        get_dummy = (libfoo, 'get_dummy', [], types.sint)
-        #
-        initval = self.call(get_dummy, [], rffi.SIGNED)
-        #
-        res = self.call(set_dummy, [initval+1], lltype.Void)
-        assert res is None
-        #
-        res = self.call(get_dummy, [], rffi.SIGNED)
-        assert res == initval+1
-
-    def test_single_float_args(self):
-        """
-            float sum_xy_float(float x, float y)
-            {
-                return x+y;
-            }
-        """
-        from ctypes import c_float # this is used only to compute the expected result
-        libfoo = self.get_libfoo()
-        func = (libfoo, 'sum_xy_float', [types.float, types.float], types.float)
-        x = r_singlefloat(12.34)
-        y = r_singlefloat(56.78)
-        res = self.call(func, [x, y], rffi.FLOAT, jitif=["singlefloats"])
-        expected = c_float(c_float(12.34).value + c_float(56.78).value).value
-        assert float(res) == expected
-
-    def test_slonglong_args(self):
-        """
-            long long sum_xy_longlong(long long x, long long y)
-            {
-                return x+y;
-            }
-        """
-        maxint32 = 2147483647 # we cannot really go above maxint on 64 bits
-                              # (and we would not test anything, as there long
-                              # is the same as long long)
-        libfoo = self.get_libfoo()
-        func = (libfoo, 'sum_xy_longlong', [types.slonglong, types.slonglong],
-                types.slonglong)
-        if IS_32_BIT:
-            x = r_longlong(maxint32+1)
-            y = r_longlong(maxint32+2)
-        else:
-            x = maxint32+1
-            y = maxint32+2
-        res = self.call(func, [x, y], rffi.LONGLONG, jitif=["longlong"])
-        expected = maxint32*2 + 3
-        assert res == expected
-
-    def test_ulonglong_args(self):
-        """
-            unsigned long long sum_xy_ulonglong(unsigned long long x,
-                                                unsigned long long y)
-            {
-                return x+y;
-            }
-        """
-        maxint64 = 9223372036854775807 # maxint64+1 does not fit into a
-                                       # longlong, but it does into a
-                                       # ulonglong
-        libfoo = self.get_libfoo()
-        func = (libfoo, 'sum_xy_ulonglong', [types.ulonglong, types.ulonglong],
-                types.ulonglong)
-        x = r_ulonglong(maxint64+1)
-        y = r_ulonglong(2)
-        res = self.call(func, [x, y], rffi.ULONGLONG, jitif=["longlong"])
-        expected = maxint64 + 3
-        assert res == expected
-
-    def test_wrong_number_of_arguments(self):
-        from pypy.rpython.llinterp import LLException
-        libfoo = self.get_libfoo()
-        func = (libfoo, 'sum_xy', [types.sint, types.double], types.sint)
-
-        glob = globals()
-        loc = locals()
-        def my_raises(s):
-            try:
-                exec s in glob, loc
-            except TypeError:
-                pass
-            except LLException, e:
-                if str(e) != "<LLException 'TypeError'>":
-                    raise
-            else:
-                assert False, 'Did not raise'
-
-        my_raises("self.call(func, [38], rffi.SIGNED)") # one less
-        my_raises("self.call(func, [38, 12.3, 42], rffi.SIGNED)") # one more
-
-
-    def test_byval_argument(self):
-        """
-            struct Point {
-                Signed x;
-                Signed y;
-            };
-
-            Signed sum_point(struct Point p) {
-                return p.x + p.y;
-            }
-        """
-        libfoo = CDLL(self.libfoo_name)
-        ffi_point_struct = make_struct_ffitype_e(0, 0, [types.signed, types.signed])
-        ffi_point = ffi_point_struct.ffistruct
-        sum_point = (libfoo, 'sum_point', [ffi_point], types.signed)
-        #
-        ARRAY = rffi.CArray(rffi.SIGNED)
-        buf = lltype.malloc(ARRAY, 2, flavor='raw')
-        buf[0] = 30
-        buf[1] = 12
-        adr = rffi.cast(rffi.VOIDP, buf)
-        res = self.call(sum_point, [('arg_raw', adr)], rffi.SIGNED,
-                        jitif=["byval"])
-        assert res == 42
-        # check that we still have the ownership on the buffer
-        assert buf[0] == 30
-        assert buf[1] == 12
-        lltype.free(buf, flavor='raw')
-        lltype.free(ffi_point_struct, flavor='raw')
-
-    def test_byval_result(self):
-        """
-            struct Point make_point(Signed x, Signed y) {
-                struct Point p;
-                p.x = x;
-                p.y = y;
-                return p;
-            }
-        """
-        libfoo = CDLL(self.libfoo_name)
-        ffi_point_struct = make_struct_ffitype_e(0, 0, [types.signed, types.signed])
-        ffi_point = ffi_point_struct.ffistruct
-
-        libfoo = CDLL(self.libfoo_name)
-        make_point = (libfoo, 'make_point', [types.signed, types.signed], ffi_point)
-        #
-        PTR = lltype.Ptr(rffi.CArray(rffi.SIGNED))
-        p = self.call(make_point, [12, 34], PTR, is_struct=True,
-                      jitif=["byval"])
-        assert p[0] == 12
-        assert p[1] == 34
-        lltype.free(p, flavor='raw')
-        lltype.free(ffi_point_struct, flavor='raw')
-
-    if os.name == 'nt':
-        def test_stdcall_simple(self):
-            """
-            int __stdcall std_diff_xy(int x, Signed y)
-            {
-                return x - y;
-            }
-            """
-            libfoo = self.get_libfoo()
-            func = (libfoo, 'std_diff_xy', [types.sint, types.signed], types.sint)
-            try:
-                self.call(func, [50, 8], lltype.Signed)
-            except ValueError, e:
-                assert e.message == 'Procedure called with not enough ' + \
-                     'arguments (8 bytes missing) or wrong calling convention'
-            except LLException, e:
-                #jitted code raises this
-                assert str(e) == "<LLException 'StackCheckError'>"
-            else:
-                assert 0, 'wrong calling convention should have raised'
-
-        def test_by_ordinal(self):
-            """
-            int AAA_first_ordinal_function()
-            {
-                return 42;
-            }
-            """
-            libfoo = self.get_libfoo()
-            f_by_name = libfoo.getpointer('AAA_first_ordinal_function' ,[],
-                                          types.uint)
-            f_by_ordinal = libfoo.getpointer_by_ordinal(1 ,[], types.uint)
-            print dir(f_by_name)
-            assert f_by_name.funcsym == f_by_ordinal.funcsym
-
-        def test_by_ordinal2(self):
-            """
-            int __stdcall BBB_second_ordinal_function()
-            {
-                return 24;
-            }
-            """
-            from pypy.rlib.libffi import WinDLL
-            dll = WinDLL(self.libfoo_name)
-            f_by_name = dll.getpointer('BBB_second_ordinal_function' ,[],
-                                          types.uint)
-            f_by_ordinal = dll.getpointer_by_ordinal(2 ,[], types.uint)
-            print dir(f_by_name)
-            assert f_by_name.funcsym == f_by_ordinal.funcsym
-            chain = ArgChain()
-            assert 24 == f_by_ordinal.call(chain, lltype.Signed, is_struct=False)
-
-
-        


More information about the pypy-commit mailing list