Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r2749:0087e2aec9ef Date: 2016-09-03 11:11 +0200 http://bitbucket.org/cffi/cffi/changeset/0087e2aec9ef/
Log: Kill the ctypes backend. diff too long, truncating to 2000 out of 2925 lines diff --git a/cffi/api.py b/cffi/api.py --- a/cffi/api.py +++ b/cffi/api.py @@ -46,20 +46,21 @@ ''' def __init__(self, backend=None): - """Create an FFI instance. The 'backend' argument is used to - select a non-default backend, mostly for tests. + """Create an FFI instance. + + The 'backend' argument is not used any more and must be set to None. + It is still present only so that 'FFI(None)' still works, and + for a few tests. """ from . import cparser, model + if backend is None: - # You need PyPy (>= 2.0 beta), or a CPython (>= 2.6) with - # _cffi_backend.so compiled. + # You need the corresponding version of PyPy, or CPython + # with the '_cffi_backend' C extension module compiled. import _cffi_backend as backend from . import __version__ assert backend.__version__ == __version__, \ "version mismatch, %s != %s" % (backend.__version__, __version__) - # (If you insist you can also try to pass the option - # 'backend=backend_ctypes.CTypesBackend()', but don't - # rely on it! It's probably not going to work well.) self._backend = backend self._lock = allocate_lock() @@ -75,8 +76,6 @@ self._init_once_cache = {} self._cdef_version = None self._embedding = None - if hasattr(backend, 'set_ffi'): - backend.set_ffi(self) for name in backend.__dict__: if name.startswith('RTLD_'): setattr(self, name, getattr(backend, name)) @@ -84,15 +83,10 @@ with self._lock: self.BVoidP = self._get_cached_btype(model.voidp_type) self.BCharA = self._get_cached_btype(model.char_array_type) - if isinstance(backend, types.ModuleType): - # _cffi_backend: attach these constants to the class - if not hasattr(FFI, 'NULL'): - FFI.NULL = self.cast(self.BVoidP, 0) - FFI.CData, FFI.CType = backend._get_types() - else: - # ctypes backend: attach these constants to the instance - self.NULL = self.cast(self.BVoidP, 0) - self.CData, self.CType = backend._get_types() + # attach these constants to the class + if not hasattr(FFI, 'NULL'): + FFI.NULL = self.cast(self.BVoidP, 0) + FFI.CData, FFI.CType = backend._get_types() def cdef(self, csource, override=False, packed=False): """Parse the given C source. This registers all declared functions, diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py deleted file mode 100644 --- a/cffi/backend_ctypes.py +++ /dev/null @@ -1,1097 +0,0 @@ -import ctypes, ctypes.util, operator, sys -from . import model - -if sys.version_info < (3,): - bytechr = chr -else: - unicode = str - long = int - xrange = range - bytechr = lambda num: bytes([num]) - -class CTypesType(type): - pass - -class CTypesData(object): - __metaclass__ = CTypesType - __slots__ = ['__weakref__'] - __name__ = '<cdata>' - - def __init__(self, *args): - raise TypeError("cannot instantiate %r" % (self.__class__,)) - - @classmethod - def _newp(cls, init): - raise TypeError("expected a pointer or array ctype, got '%s'" - % (cls._get_c_name(),)) - - @staticmethod - def _to_ctypes(value): - raise TypeError - - @classmethod - def _arg_to_ctypes(cls, *value): - try: - ctype = cls._ctype - except AttributeError: - raise TypeError("cannot create an instance of %r" % (cls,)) - if value: - res = cls._to_ctypes(*value) - if not isinstance(res, ctype): - res = cls._ctype(res) - else: - res = cls._ctype() - return res - - @classmethod - def _create_ctype_obj(cls, init): - if init is None: - return cls._arg_to_ctypes() - else: - return cls._arg_to_ctypes(init) - - @staticmethod - def _from_ctypes(ctypes_value): - raise TypeError - - @classmethod - def _get_c_name(cls, replace_with=''): - return cls._reftypename.replace(' &', replace_with) - - @classmethod - def _fix_class(cls): - cls.__name__ = 'CData<%s>' % (cls._get_c_name(),) - cls.__qualname__ = 'CData<%s>' % (cls._get_c_name(),) - cls.__module__ = 'ffi' - - def _get_own_repr(self): - raise NotImplementedError - - def _addr_repr(self, address): - if address == 0: - return 'NULL' - else: - if address < 0: - address += 1 << (8*ctypes.sizeof(ctypes.c_void_p)) - return '0x%x' % address - - def __repr__(self, c_name=None): - own = self._get_own_repr() - return '<cdata %r %s>' % (c_name or self._get_c_name(), own) - - def _convert_to_address(self, BClass): - if BClass is None: - raise TypeError("cannot convert %r to an address" % ( - self._get_c_name(),)) - else: - raise TypeError("cannot convert %r to %r" % ( - self._get_c_name(), BClass._get_c_name())) - - @classmethod - def _get_size(cls): - return ctypes.sizeof(cls._ctype) - - def _get_size_of_instance(self): - return ctypes.sizeof(self._ctype) - - @classmethod - def _cast_from(cls, source): - raise TypeError("cannot cast to %r" % (cls._get_c_name(),)) - - def _cast_to_integer(self): - return self._convert_to_address(None) - - @classmethod - def _alignment(cls): - return ctypes.alignment(cls._ctype) - - def __iter__(self): - raise TypeError("cdata %r does not support iteration" % ( - self._get_c_name()),) - - def _make_cmp(name): - cmpfunc = getattr(operator, name) - def cmp(self, other): - if isinstance(other, CTypesData): - return cmpfunc(self._convert_to_address(None), - other._convert_to_address(None)) - else: - return NotImplemented - cmp.func_name = name - return cmp - - __eq__ = _make_cmp('__eq__') - __ne__ = _make_cmp('__ne__') - __lt__ = _make_cmp('__lt__') - __le__ = _make_cmp('__le__') - __gt__ = _make_cmp('__gt__') - __ge__ = _make_cmp('__ge__') - - def __hash__(self): - return hash(type(self)) ^ hash(self._convert_to_address(None)) - - def _to_string(self, maxlen): - raise TypeError("string(): %r" % (self,)) - - -class CTypesGenericPrimitive(CTypesData): - __slots__ = [] - - def __eq__(self, other): - return self is other - - def __ne__(self, other): - return self is not other - - def __hash__(self): - return object.__hash__(self) - - def _get_own_repr(self): - return repr(self._from_ctypes(self._value)) - - -class CTypesGenericArray(CTypesData): - __slots__ = [] - - @classmethod - def _newp(cls, init): - return cls(init) - - def __iter__(self): - for i in xrange(len(self)): - yield self[i] - - def _get_own_repr(self): - return self._addr_repr(ctypes.addressof(self._blob)) - - -class CTypesGenericPtr(CTypesData): - __slots__ = ['_address', '_as_ctype_ptr'] - _automatic_casts = False - kind = "pointer" - - @classmethod - def _newp(cls, init): - return cls(init) - - @classmethod - def _cast_from(cls, source): - if source is None: - address = 0 - elif isinstance(source, CTypesData): - address = source._cast_to_integer() - elif isinstance(source, (int, long)): - address = source - else: - raise TypeError("bad type for cast to %r: %r" % - (cls, type(source).__name__)) - return cls._new_pointer_at(address) - - @classmethod - def _new_pointer_at(cls, address): - self = cls.__new__(cls) - self._address = address - self._as_ctype_ptr = ctypes.cast(address, cls._ctype) - return self - - def _get_own_repr(self): - try: - return self._addr_repr(self._address) - except AttributeError: - return '???' - - def _cast_to_integer(self): - return self._address - - def __nonzero__(self): - return bool(self._address) - __bool__ = __nonzero__ - - @classmethod - def _to_ctypes(cls, value): - if not isinstance(value, CTypesData): - raise TypeError("unexpected %s object" % type(value).__name__) - address = value._convert_to_address(cls) - return ctypes.cast(address, cls._ctype) - - @classmethod - def _from_ctypes(cls, ctypes_ptr): - address = ctypes.cast(ctypes_ptr, ctypes.c_void_p).value or 0 - return cls._new_pointer_at(address) - - @classmethod - def _initialize(cls, ctypes_ptr, value): - if value: - ctypes_ptr.contents = cls._to_ctypes(value).contents - - def _convert_to_address(self, BClass): - if (BClass in (self.__class__, None) or BClass._automatic_casts - or self._automatic_casts): - return self._address - else: - return CTypesData._convert_to_address(self, BClass) - - -class CTypesBaseStructOrUnion(CTypesData): - __slots__ = ['_blob'] - - @classmethod - def _create_ctype_obj(cls, init): - # may be overridden - raise TypeError("cannot instantiate opaque type %s" % (cls,)) - - def _get_own_repr(self): - return self._addr_repr(ctypes.addressof(self._blob)) - - @classmethod - def _offsetof(cls, fieldname): - return getattr(cls._ctype, fieldname).offset - - def _convert_to_address(self, BClass): - if getattr(BClass, '_BItem', None) is self.__class__: - return ctypes.addressof(self._blob) - else: - return CTypesData._convert_to_address(self, BClass) - - @classmethod - def _from_ctypes(cls, ctypes_struct_or_union): - self = cls.__new__(cls) - self._blob = ctypes_struct_or_union - return self - - @classmethod - def _to_ctypes(cls, value): - return value._blob - - def __repr__(self, c_name=None): - return CTypesData.__repr__(self, c_name or self._get_c_name(' &')) - - -class CTypesBackend(object): - - PRIMITIVE_TYPES = { - 'char': ctypes.c_char, - 'short': ctypes.c_short, - 'int': ctypes.c_int, - 'long': ctypes.c_long, - 'long long': ctypes.c_longlong, - 'signed char': ctypes.c_byte, - 'unsigned char': ctypes.c_ubyte, - 'unsigned short': ctypes.c_ushort, - 'unsigned int': ctypes.c_uint, - 'unsigned long': ctypes.c_ulong, - 'unsigned long long': ctypes.c_ulonglong, - 'float': ctypes.c_float, - 'double': ctypes.c_double, - '_Bool': ctypes.c_bool, - } - - for _name in ['unsigned long long', 'unsigned long', - 'unsigned int', 'unsigned short', 'unsigned char']: - _size = ctypes.sizeof(PRIMITIVE_TYPES[_name]) - PRIMITIVE_TYPES['uint%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name] - if _size == ctypes.sizeof(ctypes.c_void_p): - PRIMITIVE_TYPES['uintptr_t'] = PRIMITIVE_TYPES[_name] - if _size == ctypes.sizeof(ctypes.c_size_t): - PRIMITIVE_TYPES['size_t'] = PRIMITIVE_TYPES[_name] - - for _name in ['long long', 'long', 'int', 'short', 'signed char']: - _size = ctypes.sizeof(PRIMITIVE_TYPES[_name]) - PRIMITIVE_TYPES['int%d_t' % (8*_size)] = PRIMITIVE_TYPES[_name] - if _size == ctypes.sizeof(ctypes.c_void_p): - PRIMITIVE_TYPES['intptr_t'] = PRIMITIVE_TYPES[_name] - PRIMITIVE_TYPES['ptrdiff_t'] = PRIMITIVE_TYPES[_name] - if _size == ctypes.sizeof(ctypes.c_size_t): - PRIMITIVE_TYPES['ssize_t'] = PRIMITIVE_TYPES[_name] - - - def __init__(self): - self.RTLD_LAZY = 0 # not supported anyway by ctypes - self.RTLD_NOW = 0 - self.RTLD_GLOBAL = ctypes.RTLD_GLOBAL - self.RTLD_LOCAL = ctypes.RTLD_LOCAL - - def set_ffi(self, ffi): - self.ffi = ffi - - def _get_types(self): - return CTypesData, CTypesType - - def load_library(self, path, flags=0): - cdll = ctypes.CDLL(path, flags) - return CTypesLibrary(self, cdll) - - def new_void_type(self): - class CTypesVoid(CTypesData): - __slots__ = [] - _reftypename = 'void &' - @staticmethod - def _from_ctypes(novalue): - return None - @staticmethod - def _to_ctypes(novalue): - if novalue is not None: - raise TypeError("None expected, got %s object" % - (type(novalue).__name__,)) - return None - CTypesVoid._fix_class() - return CTypesVoid - - def new_primitive_type(self, name): - if name == 'wchar_t': - raise NotImplementedError(name) - ctype = self.PRIMITIVE_TYPES[name] - if name == 'char': - kind = 'char' - elif name in ('float', 'double'): - kind = 'float' - else: - if name in ('signed char', 'unsigned char'): - kind = 'byte' - elif name == '_Bool': - kind = 'bool' - else: - kind = 'int' - is_signed = (ctype(-1).value == -1) - # - def _cast_source_to_int(source): - if isinstance(source, (int, long, float)): - source = int(source) - elif isinstance(source, CTypesData): - source = source._cast_to_integer() - elif isinstance(source, bytes): - source = ord(source) - elif source is None: - source = 0 - else: - raise TypeError("bad type for cast to %r: %r" % - (CTypesPrimitive, type(source).__name__)) - return source - # - kind1 = kind - class CTypesPrimitive(CTypesGenericPrimitive): - __slots__ = ['_value'] - _ctype = ctype - _reftypename = '%s &' % name - kind = kind1 - - def __init__(self, value): - self._value = value - - @staticmethod - def _create_ctype_obj(init): - if init is None: - return ctype() - return ctype(CTypesPrimitive._to_ctypes(init)) - - if kind == 'int' or kind == 'byte': - @classmethod - def _cast_from(cls, source): - source = _cast_source_to_int(source) - source = ctype(source).value # cast within range - return cls(source) - def __int__(self): - return self._value - - if kind == 'bool': - @classmethod - def _cast_from(cls, source): - if not isinstance(source, (int, long, float)): - source = _cast_source_to_int(source) - return cls(bool(source)) - def __int__(self): - return self._value - - if kind == 'char': - @classmethod - def _cast_from(cls, source): - source = _cast_source_to_int(source) - source = bytechr(source & 0xFF) - return cls(source) - def __int__(self): - return ord(self._value) - - if kind == 'float': - @classmethod - def _cast_from(cls, source): - if isinstance(source, float): - pass - elif isinstance(source, CTypesGenericPrimitive): - if hasattr(source, '__float__'): - source = float(source) - else: - source = int(source) - else: - source = _cast_source_to_int(source) - source = ctype(source).value # fix precision - return cls(source) - def __int__(self): - return int(self._value) - def __float__(self): - return self._value - - _cast_to_integer = __int__ - - if kind == 'int' or kind == 'byte' or kind == 'bool': - @staticmethod - def _to_ctypes(x): - if not isinstance(x, (int, long)): - if isinstance(x, CTypesData): - x = int(x) - else: - raise TypeError("integer expected, got %s" % - type(x).__name__) - if ctype(x).value != x: - if not is_signed and x < 0: - raise OverflowError("%s: negative integer" % name) - else: - raise OverflowError("%s: integer out of bounds" - % name) - return x - - if kind == 'char': - @staticmethod - def _to_ctypes(x): - if isinstance(x, bytes) and len(x) == 1: - return x - if isinstance(x, CTypesPrimitive): # <CData <char>> - return x._value - raise TypeError("character expected, got %s" % - type(x).__name__) - def __nonzero__(self): - return ord(self._value) != 0 - else: - def __nonzero__(self): - return self._value != 0 - __bool__ = __nonzero__ - - if kind == 'float': - @staticmethod - def _to_ctypes(x): - if not isinstance(x, (int, long, float, CTypesData)): - raise TypeError("float expected, got %s" % - type(x).__name__) - return ctype(x).value - - @staticmethod - def _from_ctypes(value): - return getattr(value, 'value', value) - - @staticmethod - def _initialize(blob, init): - blob.value = CTypesPrimitive._to_ctypes(init) - - if kind == 'char': - def _to_string(self, maxlen): - return self._value - if kind == 'byte': - def _to_string(self, maxlen): - return chr(self._value & 0xff) - # - CTypesPrimitive._fix_class() - return CTypesPrimitive - - def new_pointer_type(self, BItem): - getbtype = self.ffi._get_cached_btype - if BItem is getbtype(model.PrimitiveType('char')): - kind = 'charp' - elif BItem in (getbtype(model.PrimitiveType('signed char')), - getbtype(model.PrimitiveType('unsigned char'))): - kind = 'bytep' - elif BItem is getbtype(model.void_type): - kind = 'voidp' - else: - kind = 'generic' - # - class CTypesPtr(CTypesGenericPtr): - __slots__ = ['_own'] - if kind == 'charp': - __slots__ += ['__as_strbuf'] - _BItem = BItem - if hasattr(BItem, '_ctype'): - _ctype = ctypes.POINTER(BItem._ctype) - _bitem_size = ctypes.sizeof(BItem._ctype) - else: - _ctype = ctypes.c_void_p - if issubclass(BItem, CTypesGenericArray): - _reftypename = BItem._get_c_name('(* &)') - else: - _reftypename = BItem._get_c_name(' * &') - - def __init__(self, init): - ctypeobj = BItem._create_ctype_obj(init) - if kind == 'charp': - self.__as_strbuf = ctypes.create_string_buffer( - ctypeobj.value + b'\x00') - self._as_ctype_ptr = ctypes.cast( - self.__as_strbuf, self._ctype) - else: - self._as_ctype_ptr = ctypes.pointer(ctypeobj) - self._address = ctypes.cast(self._as_ctype_ptr, - ctypes.c_void_p).value - self._own = True - - def __add__(self, other): - if isinstance(other, (int, long)): - return self._new_pointer_at(self._address + - other * self._bitem_size) - else: - return NotImplemented - - def __sub__(self, other): - if isinstance(other, (int, long)): - return self._new_pointer_at(self._address - - other * self._bitem_size) - elif type(self) is type(other): - return (self._address - other._address) // self._bitem_size - else: - return NotImplemented - - def __getitem__(self, index): - if getattr(self, '_own', False) and index != 0: - raise IndexError - return BItem._from_ctypes(self._as_ctype_ptr[index]) - - def __setitem__(self, index, value): - self._as_ctype_ptr[index] = BItem._to_ctypes(value) - - if kind == 'charp' or kind == 'voidp': - @classmethod - def _arg_to_ctypes(cls, *value): - if value and isinstance(value[0], bytes): - return ctypes.c_char_p(value[0]) - else: - return super(CTypesPtr, cls)._arg_to_ctypes(*value) - - if kind == 'charp' or kind == 'bytep': - def _to_string(self, maxlen): - if maxlen < 0: - maxlen = sys.maxsize - p = ctypes.cast(self._as_ctype_ptr, - ctypes.POINTER(ctypes.c_char)) - n = 0 - while n < maxlen and p[n] != b'\x00': - n += 1 - return b''.join([p[i] for i in range(n)]) - - def _get_own_repr(self): - if getattr(self, '_own', False): - return 'owning %d bytes' % ( - ctypes.sizeof(self._as_ctype_ptr.contents),) - return super(CTypesPtr, self)._get_own_repr() - # - if (BItem is self.ffi._get_cached_btype(model.void_type) or - BItem is self.ffi._get_cached_btype(model.PrimitiveType('char'))): - CTypesPtr._automatic_casts = True - # - CTypesPtr._fix_class() - return CTypesPtr - - def new_array_type(self, CTypesPtr, length): - if length is None: - brackets = ' &[]' - else: - brackets = ' &[%d]' % length - BItem = CTypesPtr._BItem - getbtype = self.ffi._get_cached_btype - if BItem is getbtype(model.PrimitiveType('char')): - kind = 'char' - elif BItem in (getbtype(model.PrimitiveType('signed char')), - getbtype(model.PrimitiveType('unsigned char'))): - kind = 'byte' - else: - kind = 'generic' - # - class CTypesArray(CTypesGenericArray): - __slots__ = ['_blob', '_own'] - if length is not None: - _ctype = BItem._ctype * length - else: - __slots__.append('_ctype') - _reftypename = BItem._get_c_name(brackets) - _declared_length = length - _CTPtr = CTypesPtr - - def __init__(self, init): - if length is None: - if isinstance(init, (int, long)): - len1 = init - init = None - elif kind == 'char' and isinstance(init, bytes): - len1 = len(init) + 1 # extra null - else: - init = tuple(init) - len1 = len(init) - self._ctype = BItem._ctype * len1 - self._blob = self._ctype() - self._own = True - if init is not None: - self._initialize(self._blob, init) - - @staticmethod - def _initialize(blob, init): - if isinstance(init, bytes): - init = [init[i:i+1] for i in range(len(init))] - else: - init = tuple(init) - if len(init) > len(blob): - raise IndexError("too many initializers") - addr = ctypes.cast(blob, ctypes.c_void_p).value - PTR = ctypes.POINTER(BItem._ctype) - itemsize = ctypes.sizeof(BItem._ctype) - for i, value in enumerate(init): - p = ctypes.cast(addr + i * itemsize, PTR) - BItem._initialize(p.contents, value) - - def __len__(self): - return len(self._blob) - - def __getitem__(self, index): - if not (0 <= index < len(self._blob)): - raise IndexError - return BItem._from_ctypes(self._blob[index]) - - def __setitem__(self, index, value): - if not (0 <= index < len(self._blob)): - raise IndexError - self._blob[index] = BItem._to_ctypes(value) - - if kind == 'char' or kind == 'byte': - def _to_string(self, maxlen): - if maxlen < 0: - maxlen = len(self._blob) - p = ctypes.cast(self._blob, - ctypes.POINTER(ctypes.c_char)) - n = 0 - while n < maxlen and p[n] != b'\x00': - n += 1 - return b''.join([p[i] for i in range(n)]) - - def _get_own_repr(self): - if getattr(self, '_own', False): - return 'owning %d bytes' % (ctypes.sizeof(self._blob),) - return super(CTypesArray, self)._get_own_repr() - - def _convert_to_address(self, BClass): - if BClass in (CTypesPtr, None) or BClass._automatic_casts: - return ctypes.addressof(self._blob) - else: - return CTypesData._convert_to_address(self, BClass) - - @staticmethod - def _from_ctypes(ctypes_array): - self = CTypesArray.__new__(CTypesArray) - self._blob = ctypes_array - return self - - @staticmethod - def _arg_to_ctypes(value): - return CTypesPtr._arg_to_ctypes(value) - - def __add__(self, other): - if isinstance(other, (int, long)): - return CTypesPtr._new_pointer_at( - ctypes.addressof(self._blob) + - other * ctypes.sizeof(BItem._ctype)) - else: - return NotImplemented - - @classmethod - def _cast_from(cls, source): - raise NotImplementedError("casting to %r" % ( - cls._get_c_name(),)) - # - CTypesArray._fix_class() - return CTypesArray - - def _new_struct_or_union(self, kind, name, base_ctypes_class): - # - class struct_or_union(base_ctypes_class): - pass - struct_or_union.__name__ = '%s_%s' % (kind, name) - kind1 = kind - # - class CTypesStructOrUnion(CTypesBaseStructOrUnion): - __slots__ = ['_blob'] - _ctype = struct_or_union - _reftypename = '%s &' % (name,) - _kind = kind = kind1 - # - CTypesStructOrUnion._fix_class() - return CTypesStructOrUnion - - def new_struct_type(self, name): - return self._new_struct_or_union('struct', name, ctypes.Structure) - - def new_union_type(self, name): - return self._new_struct_or_union('union', name, ctypes.Union) - - def complete_struct_or_union(self, CTypesStructOrUnion, fields, tp, - totalsize=-1, totalalignment=-1, sflags=0): - if totalsize >= 0 or totalalignment >= 0: - raise NotImplementedError("the ctypes backend of CFFI does not support " - "structures completed by verify(); please " - "compile and install the _cffi_backend module.") - struct_or_union = CTypesStructOrUnion._ctype - fnames = [fname for (fname, BField, bitsize) in fields] - btypes = [BField for (fname, BField, bitsize) in fields] - bitfields = [bitsize for (fname, BField, bitsize) in fields] - # - bfield_types = {} - cfields = [] - for (fname, BField, bitsize) in fields: - if bitsize < 0: - cfields.append((fname, BField._ctype)) - bfield_types[fname] = BField - else: - cfields.append((fname, BField._ctype, bitsize)) - bfield_types[fname] = Ellipsis - if sflags & 8: - struct_or_union._pack_ = 1 - struct_or_union._fields_ = cfields - CTypesStructOrUnion._bfield_types = bfield_types - # - @staticmethod - def _create_ctype_obj(init): - result = struct_or_union() - if init is not None: - initialize(result, init) - return result - CTypesStructOrUnion._create_ctype_obj = _create_ctype_obj - # - def initialize(blob, init): - if is_union: - if len(init) > 1: - raise ValueError("union initializer: %d items given, but " - "only one supported (use a dict if needed)" - % (len(init),)) - if not isinstance(init, dict): - if isinstance(init, (bytes, unicode)): - raise TypeError("union initializer: got a str") - init = tuple(init) - if len(init) > len(fnames): - raise ValueError("too many values for %s initializer" % - CTypesStructOrUnion._get_c_name()) - init = dict(zip(fnames, init)) - addr = ctypes.addressof(blob) - for fname, value in init.items(): - BField, bitsize = name2fieldtype[fname] - assert bitsize < 0, \ - "not implemented: initializer with bit fields" - offset = CTypesStructOrUnion._offsetof(fname) - PTR = ctypes.POINTER(BField._ctype) - p = ctypes.cast(addr + offset, PTR) - BField._initialize(p.contents, value) - is_union = CTypesStructOrUnion._kind == 'union' - name2fieldtype = dict(zip(fnames, zip(btypes, bitfields))) - # - for fname, BField, bitsize in fields: - if fname == '': - raise NotImplementedError("nested anonymous structs/unions") - if hasattr(CTypesStructOrUnion, fname): - raise ValueError("the field name %r conflicts in " - "the ctypes backend" % fname) - if bitsize < 0: - def getter(self, fname=fname, BField=BField, - offset=CTypesStructOrUnion._offsetof(fname), - PTR=ctypes.POINTER(BField._ctype)): - addr = ctypes.addressof(self._blob) - p = ctypes.cast(addr + offset, PTR) - return BField._from_ctypes(p.contents) - def setter(self, value, fname=fname, BField=BField): - setattr(self._blob, fname, BField._to_ctypes(value)) - # - if issubclass(BField, CTypesGenericArray): - setter = None - if BField._declared_length == 0: - def getter(self, fname=fname, BFieldPtr=BField._CTPtr, - offset=CTypesStructOrUnion._offsetof(fname), - PTR=ctypes.POINTER(BField._ctype)): - addr = ctypes.addressof(self._blob) - p = ctypes.cast(addr + offset, PTR) - return BFieldPtr._from_ctypes(p) - # - else: - def getter(self, fname=fname, BField=BField): - return BField._from_ctypes(getattr(self._blob, fname)) - def setter(self, value, fname=fname, BField=BField): - # xxx obscure workaround - value = BField._to_ctypes(value) - oldvalue = getattr(self._blob, fname) - setattr(self._blob, fname, value) - if value != getattr(self._blob, fname): - setattr(self._blob, fname, oldvalue) - raise OverflowError("value too large for bitfield") - setattr(CTypesStructOrUnion, fname, property(getter, setter)) - # - CTypesPtr = self.ffi._get_cached_btype(model.PointerType(tp)) - for fname in fnames: - if hasattr(CTypesPtr, fname): - raise ValueError("the field name %r conflicts in " - "the ctypes backend" % fname) - def getter(self, fname=fname): - return getattr(self[0], fname) - def setter(self, value, fname=fname): - setattr(self[0], fname, value) - setattr(CTypesPtr, fname, property(getter, setter)) - - def new_function_type(self, BArgs, BResult, has_varargs): - nameargs = [BArg._get_c_name() for BArg in BArgs] - if has_varargs: - nameargs.append('...') - nameargs = ', '.join(nameargs) - # - class CTypesFunctionPtr(CTypesGenericPtr): - __slots__ = ['_own_callback', '_name'] - _ctype = ctypes.CFUNCTYPE(getattr(BResult, '_ctype', None), - *[BArg._ctype for BArg in BArgs], - use_errno=True) - _reftypename = BResult._get_c_name('(* &)(%s)' % (nameargs,)) - - def __init__(self, init, error=None): - # create a callback to the Python callable init() - import traceback - assert not has_varargs, "varargs not supported for callbacks" - if getattr(BResult, '_ctype', None) is not None: - error = BResult._from_ctypes( - BResult._create_ctype_obj(error)) - else: - error = None - def callback(*args): - args2 = [] - for arg, BArg in zip(args, BArgs): - args2.append(BArg._from_ctypes(arg)) - try: - res2 = init(*args2) - res2 = BResult._to_ctypes(res2) - except: - traceback.print_exc() - res2 = error - if issubclass(BResult, CTypesGenericPtr): - if res2: - res2 = ctypes.cast(res2, ctypes.c_void_p).value - # .value: http://bugs.python.org/issue1574593 - else: - res2 = None - #print repr(res2) - return res2 - if issubclass(BResult, CTypesGenericPtr): - # The only pointers callbacks can return are void*s: - # http://bugs.python.org/issue5710 - callback_ctype = ctypes.CFUNCTYPE( - ctypes.c_void_p, - *[BArg._ctype for BArg in BArgs], - use_errno=True) - else: - callback_ctype = CTypesFunctionPtr._ctype - self._as_ctype_ptr = callback_ctype(callback) - self._address = ctypes.cast(self._as_ctype_ptr, - ctypes.c_void_p).value - self._own_callback = init - - @staticmethod - def _initialize(ctypes_ptr, value): - if value: - raise NotImplementedError("ctypes backend: not supported: " - "initializers for function pointers") - - def __repr__(self): - c_name = getattr(self, '_name', None) - if c_name: - i = self._reftypename.index('(* &)') - if self._reftypename[i-1] not in ' )*': - c_name = ' ' + c_name - c_name = self._reftypename.replace('(* &)', c_name) - return CTypesData.__repr__(self, c_name) - - def _get_own_repr(self): - if getattr(self, '_own_callback', None) is not None: - return 'calling %r' % (self._own_callback,) - return super(CTypesFunctionPtr, self)._get_own_repr() - - def __call__(self, *args): - if has_varargs: - assert len(args) >= len(BArgs) - extraargs = args[len(BArgs):] - args = args[:len(BArgs)] - else: - assert len(args) == len(BArgs) - ctypes_args = [] - for arg, BArg in zip(args, BArgs): - ctypes_args.append(BArg._arg_to_ctypes(arg)) - if has_varargs: - for i, arg in enumerate(extraargs): - if arg is None: - ctypes_args.append(ctypes.c_void_p(0)) # NULL - continue - if not isinstance(arg, CTypesData): - raise TypeError( - "argument %d passed in the variadic part " - "needs to be a cdata object (got %s)" % - (1 + len(BArgs) + i, type(arg).__name__)) - ctypes_args.append(arg._arg_to_ctypes(arg)) - result = self._as_ctype_ptr(*ctypes_args) - return BResult._from_ctypes(result) - # - CTypesFunctionPtr._fix_class() - return CTypesFunctionPtr - - def new_enum_type(self, name, enumerators, enumvalues, CTypesInt): - assert isinstance(name, str) - reverse_mapping = dict(zip(reversed(enumvalues), - reversed(enumerators))) - # - class CTypesEnum(CTypesInt): - __slots__ = [] - _reftypename = '%s &' % name - - def _get_own_repr(self): - value = self._value - try: - return '%d: %s' % (value, reverse_mapping[value]) - except KeyError: - return str(value) - - def _to_string(self, maxlen): - value = self._value - try: - return reverse_mapping[value] - except KeyError: - return str(value) - # - CTypesEnum._fix_class() - return CTypesEnum - - def get_errno(self): - return ctypes.get_errno() - - def set_errno(self, value): - ctypes.set_errno(value) - - def string(self, b, maxlen=-1): - return b._to_string(maxlen) - - def buffer(self, bptr, size=-1): - raise NotImplementedError("buffer() with ctypes backend") - - def sizeof(self, cdata_or_BType): - if isinstance(cdata_or_BType, CTypesData): - return cdata_or_BType._get_size_of_instance() - else: - assert issubclass(cdata_or_BType, CTypesData) - return cdata_or_BType._get_size() - - def alignof(self, BType): - assert issubclass(BType, CTypesData) - return BType._alignment() - - def newp(self, BType, source): - if not issubclass(BType, CTypesData): - raise TypeError - return BType._newp(source) - - def cast(self, BType, source): - return BType._cast_from(source) - - def callback(self, BType, source, error, onerror): - assert onerror is None # XXX not implemented - return BType(source, error) - - def gcp(self, cdata, destructor): - BType = self.typeof(cdata) - - if destructor is None: - if not (hasattr(BType, '_gcp_type') and - BType._gcp_type is BType): - raise TypeError("Can remove destructor only on a object " - "previously returned by ffi.gc()") - cdata._destructor = None - return None - - try: - gcp_type = BType._gcp_type - except AttributeError: - class CTypesDataGcp(BType): - __slots__ = ['_orig', '_destructor'] - def __del__(self): - if self._destructor is not None: - self._destructor(self._orig) - gcp_type = BType._gcp_type = CTypesDataGcp - new_cdata = self.cast(gcp_type, cdata) - new_cdata._orig = cdata - new_cdata._destructor = destructor - return new_cdata - - typeof = type - - def getcname(self, BType, replace_with): - return BType._get_c_name(replace_with) - - def typeoffsetof(self, BType, fieldname, num=0): - if isinstance(fieldname, str): - if num == 0 and issubclass(BType, CTypesGenericPtr): - BType = BType._BItem - if not issubclass(BType, CTypesBaseStructOrUnion): - raise TypeError("expected a struct or union ctype") - BField = BType._bfield_types[fieldname] - if BField is Ellipsis: - raise TypeError("not supported for bitfields") - return (BField, BType._offsetof(fieldname)) - elif isinstance(fieldname, (int, long)): - if issubclass(BType, CTypesGenericArray): - BType = BType._CTPtr - if not issubclass(BType, CTypesGenericPtr): - raise TypeError("expected an array or ptr ctype") - BItem = BType._BItem - offset = BItem._get_size() * fieldname - if offset > sys.maxsize: - raise OverflowError - return (BItem, offset) - else: - raise TypeError(type(fieldname)) - - def rawaddressof(self, BTypePtr, cdata, offset=None): - if isinstance(cdata, CTypesBaseStructOrUnion): - ptr = ctypes.pointer(type(cdata)._to_ctypes(cdata)) - elif isinstance(cdata, CTypesGenericPtr): - if offset is None or not issubclass(type(cdata)._BItem, - CTypesBaseStructOrUnion): - raise TypeError("unexpected cdata type") - ptr = type(cdata)._to_ctypes(cdata) - elif isinstance(cdata, CTypesGenericArray): - ptr = type(cdata)._to_ctypes(cdata) - else: - raise TypeError("expected a <cdata 'struct-or-union'>") - if offset: - ptr = ctypes.cast( - ctypes.c_void_p( - ctypes.cast(ptr, ctypes.c_void_p).value + offset), - type(ptr)) - return BTypePtr._from_ctypes(ptr) - - -class CTypesLibrary(object): - - def __init__(self, backend, cdll): - self.backend = backend - self.cdll = cdll - - def load_function(self, BType, name): - c_func = getattr(self.cdll, name) - funcobj = BType._from_ctypes(c_func) - funcobj._name = name - return funcobj - - def read_variable(self, BType, name): - try: - ctypes_obj = BType._ctype.in_dll(self.cdll, name) - except AttributeError as e: - raise NotImplementedError(e) - return BType._from_ctypes(ctypes_obj) - - def write_variable(self, BType, name, value): - new_ctypes_obj = BType._to_ctypes(value) - ctypes_obj = BType._ctype.in_dll(self.cdll, name) - ctypes.memmove(ctypes.addressof(ctypes_obj), - ctypes.addressof(new_ctypes_obj), - ctypes.sizeof(BType._ctype)) diff --git a/doc/source/whatsnew.rst b/doc/source/whatsnew.rst --- a/doc/source/whatsnew.rst +++ b/doc/source/whatsnew.rst @@ -23,6 +23,10 @@ argument (in older versions, a copy would be made). This used to be a CPython-only optimization. +* Removed the ctypes backend. If ``_cffi_backend`` was not compiled, + you could ask (using an undocumented interface) for ``backend_ctypes`` + instead. That was never fully functional and long deprecated. + v1.7 ==== diff --git a/testing/cffi0/backend_tests.py b/testing/cffi0/test_backend.py rename from testing/cffi0/backend_tests.py rename to testing/cffi0/test_backend.py --- a/testing/cffi0/backend_tests.py +++ b/testing/cffi0/test_backend.py @@ -11,10 +11,10 @@ SIZE_OF_WCHAR = ctypes.sizeof(ctypes.c_wchar) -class BackendTests: +class TestBackend(object): def test_integer_ranges(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() for (c_type, size) in [('char', 1), ('short', 2), ('short int', 2), @@ -34,7 +34,7 @@ self._test_int_type(ffi, c_decl, size, unsigned) def test_fixedsize_int(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() for size in [1, 2, 4, 8]: self._test_int_type(ffi, 'int%d_t' % (8*size), size, False) self._test_int_type(ffi, 'uint%d_t' % (8*size), size, True) @@ -79,12 +79,12 @@ assert ffi.new(c_decl_ptr, long(max))[0] == max def test_new_unsupported_type(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() e = py.test.raises(TypeError, ffi.new, "int") assert str(e.value) == "expected a pointer or array ctype, got 'int'" def test_new_single_integer(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() p = ffi.new("int *") # similar to ffi.new("int[1]") assert p[0] == 0 p[0] = -123 @@ -94,14 +94,14 @@ assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT def test_new_array_no_arg(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() p = ffi.new("int[10]") # the object was zero-initialized: for i in range(10): assert p[i] == 0 def test_array_indexing(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() p = ffi.new("int[10]") p[0] = 42 p[9] = 43 @@ -113,7 +113,7 @@ py.test.raises(IndexError, "p[-1] = 44") def test_new_array_args(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() # this tries to be closer to C: where we say "int x[5] = {10, 20, ..}" # then here we must enclose the items in a list p = ffi.new("int[5]", [10, 20, 30, 40, 50]) @@ -132,7 +132,7 @@ assert repr(p) == "<cdata 'int[4]' owning %d bytes>" % (4*SIZE_OF_INT) def test_new_array_varsize(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() p = ffi.new("int[]", 10) # a single integer is the length assert p[9] == 0 py.test.raises(IndexError, "p[10]") @@ -151,7 +151,7 @@ assert repr(p) == "<cdata 'int[]' owning 0 bytes>" def test_pointer_init(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() n = ffi.new("int *", 24) a = ffi.new("int *[10]", [ffi.NULL, ffi.NULL, n, n, ffi.NULL]) for i in range(10): @@ -160,14 +160,14 @@ assert a[2] == a[3] == n def test_cannot_cast(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() a = ffi.new("short int[10]") e = py.test.raises(TypeError, ffi.new, "long int **", a) msg = str(e.value) assert "'short[10]'" in msg and "'long *'" in msg def test_new_pointer_to_array(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() a = ffi.new("int[4]", [100, 102, 104, 106]) p = ffi.new("int **", a) assert p[0] == ffi.cast("int *", a) @@ -180,7 +180,7 @@ # keepalive: a def test_pointer_direct(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() p = ffi.cast("int*", 0) assert p is not None assert bool(p) is False @@ -195,9 +195,11 @@ assert p[0] == 123 assert p[1] == 456 + TypeRepr = "<ctype '%s'>" + def test_repr(self): typerepr = self.TypeRepr - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo { short a, b, c; };") p = ffi.cast("short unsigned int", 0) assert repr(p) == "<cdata 'unsigned short' 0>" @@ -248,7 +250,7 @@ assert repr(ffi.typeof(q)) == typerepr % "struct foo" def test_new_array_of_array(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() p = ffi.new("int[3][4]") p[0][0] = 10 p[2][3] = 33 @@ -257,12 +259,12 @@ py.test.raises(IndexError, "p[1][-1]") def test_constructor_array_of_array(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() p = ffi.new("int[3][2]", [[10, 11], [12, 13], [14, 15]]) assert p[2][1] == 15 def test_new_array_of_pointer_1(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() n = ffi.new("int*", 99) p = ffi.new("int*[4]") p[3] = n @@ -271,7 +273,7 @@ assert a[0] == 99 def test_new_array_of_pointer_2(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() n = ffi.new("int[1]", [99]) p = ffi.new("int*[4]") p[3] = n @@ -280,7 +282,7 @@ assert a[0] == 99 def test_char(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() assert ffi.new("char*", b"\xff")[0] == b'\xff' assert ffi.new("char*")[0] == b'\x00' assert int(ffi.cast("char", 300)) == 300 - 256 @@ -317,7 +319,7 @@ py.test.skip("NotImplementedError: wchar_t") def test_wchar_t(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() self.check_wchar_t(ffi) assert ffi.new("wchar_t*", u+'x')[0] == u+'x' assert ffi.new("wchar_t*", u+'\u1234')[0] == u+'\u1234' @@ -372,7 +374,7 @@ py.test.raises(IndexError, ffi.new, "wchar_t[2]", u+"abc") def test_none_as_null_doesnt_work(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() p = ffi.new("int*[1]") assert p[0] is not None assert p[0] != None @@ -387,7 +389,7 @@ assert p[0] == ffi.NULL def test_float(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() p = ffi.new("float[]", [-2, -2.5]) assert p[0] == -2.0 assert p[1] == -2.5 @@ -412,7 +414,7 @@ assert p[0] == INF # infinite, not enough precision def test_struct_simple(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo { int a; short b, c; };") s = ffi.new("struct foo*") assert s.a == s.b == s.c == 0 @@ -431,7 +433,7 @@ py.test.raises(ValueError, ffi.new, "struct foo*", [1, 2, 3, 4]) def test_constructor_struct_from_dict(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo { int a; short b, c; };") s = ffi.new("struct foo*", {'b': 123, 'c': 456}) assert s.a == 0 @@ -440,7 +442,7 @@ py.test.raises(KeyError, ffi.new, "struct foo*", {'d': 456}) def test_struct_pointer(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo { int a; short b, c; };") s = ffi.new("struct foo*") assert s[0].a == s[0].b == s[0].c == 0 @@ -450,13 +452,13 @@ py.test.raises(IndexError, "s[1]") def test_struct_opaque(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() py.test.raises(TypeError, ffi.new, "struct baz*") p = ffi.new("struct baz **") # this works assert p[0] == ffi.NULL def test_pointer_to_struct(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo { int a; short b, c; };") s = ffi.new("struct foo *") s.a = -42 @@ -478,7 +480,7 @@ assert p[0][0].a == -46 def test_constructor_struct_of_array(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo { int a[2]; char b[3]; };") s = ffi.new("struct foo *", [[10, 11], [b'a', b'b', b'c']]) assert s.a[1] == 11 @@ -489,7 +491,7 @@ assert s.b[2] == b'c' def test_recursive_struct(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo { int value; struct foo *next; };") s = ffi.new("struct foo*") t = ffi.new("struct foo*") @@ -500,7 +502,7 @@ assert s.next.value == 456 def test_union_simple(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("union foo { int a; short b, c; };") u = ffi.new("union foo*") assert u.a == u.b == u.c == 0 @@ -515,13 +517,13 @@ assert repr(u) == "<cdata 'union foo *' owning %d bytes>" % SIZE_OF_INT def test_union_opaque(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() py.test.raises(TypeError, ffi.new, "union baz *") u = ffi.new("union baz **") # this works assert u[0] == ffi.NULL def test_union_initializer(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("union foo { char a; int b; };") py.test.raises(TypeError, ffi.new, "union foo*", b'A') py.test.raises(TypeError, ffi.new, "union foo*", 5) @@ -536,7 +538,7 @@ assert u.b == 0 def test_sizeof_type(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef(""" struct foo { int a; short b, c, d; }; union foo { int a; short b, c, d; }; @@ -553,7 +555,7 @@ assert size == expected_size, (size, expected_size, ctype) def test_sizeof_cdata(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() assert ffi.sizeof(ffi.new("short*")) == SIZE_OF_PTR assert ffi.sizeof(ffi.cast("short", 123)) == SIZE_OF_SHORT # @@ -562,7 +564,7 @@ assert ffi.sizeof(a) == 5 * SIZE_OF_INT def test_string_from_char_pointer(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() x = ffi.new("char*", b"x") assert str(x) == repr(x) assert ffi.string(x) == b"x" @@ -570,7 +572,7 @@ py.test.raises(TypeError, ffi.new, "char*", unicode("foo")) def test_unicode_from_wchar_pointer(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() self.check_wchar_t(ffi) x = ffi.new("wchar_t*", u+"x") assert unicode(x) == unicode(repr(x)) @@ -578,7 +580,7 @@ assert ffi.string(ffi.new("wchar_t*", u+"\x00")) == u+"" def test_string_from_char_array(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() p = ffi.new("char[]", b"hello.") p[5] = b'!' assert ffi.string(p) == b"hello!" @@ -595,7 +597,7 @@ assert ffi.string(p) == b'hello' def test_string_from_wchar_array(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() self.check_wchar_t(ffi) assert ffi.string(ffi.cast("wchar_t", "x")) == u+"x" assert ffi.string(ffi.cast("wchar_t", u+"x")) == u+"x" @@ -623,7 +625,7 @@ def test_fetch_const_char_p_field(self): # 'const' is ignored so far - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo { const char *name; };") t = ffi.new("const char[]", b"testing") s = ffi.new("struct foo*", [t]) @@ -635,7 +637,7 @@ def test_fetch_const_wchar_p_field(self): # 'const' is ignored so far - ffi = FFI(backend=self.Backend()) + ffi = FFI() self.check_wchar_t(ffi) ffi.cdef("struct foo { const wchar_t *name; };") t = ffi.new("const wchar_t[]", u+"testing") @@ -646,7 +648,7 @@ assert s.name == ffi.NULL def test_voidp(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() py.test.raises(TypeError, ffi.new, "void*") p = ffi.new("void **") assert p[0] == ffi.NULL @@ -667,7 +669,7 @@ py.test.raises(TypeError, "s.r = b") # fails def test_functionptr_simple(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() py.test.raises(TypeError, ffi.callback, "int(*)(int)", 0) def cb(n): return n + 1 @@ -692,12 +694,12 @@ assert res == 46 def test_functionptr_advanced(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() t = ffi.typeof("int(*(*)(int))(int)") assert repr(t) == self.TypeRepr % "int(*(*)(int))(int)" def test_functionptr_voidptr_return(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() def cb(): return ffi.NULL p = ffi.callback("void*(*)()", cb) @@ -713,7 +715,7 @@ assert res == void_ptr def test_functionptr_intptr_return(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() def cb(): return ffi.NULL p = ffi.callback("int*(*)()", cb) @@ -735,7 +737,7 @@ assert res == int_array_ptr def test_functionptr_void_return(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() def foo(): pass foo_cb = ffi.callback("void foo()", foo) @@ -743,7 +745,7 @@ assert result is None def test_char_cast(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() p = ffi.cast("int", b'\x01') assert ffi.typeof(p) is ffi.typeof("int") assert int(p) == 1 @@ -755,7 +757,7 @@ assert int(p) == 0x81 def test_wchar_cast(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() self.check_wchar_t(ffi) p = ffi.cast("int", ffi.cast("wchar_t", u+'\u1234')) assert int(p) == 0x1234 @@ -771,7 +773,7 @@ assert int(p) == 0x1234 def test_cast_array_to_charp(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() a = ffi.new("short int[]", [0x1234, 0x5678]) p = ffi.cast("char*", a) data = b''.join([p[i] for i in range(4)]) @@ -781,7 +783,7 @@ assert data == b'\x12\x34\x56\x78' def test_cast_between_pointers(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() a = ffi.new("short int[]", [0x1234, 0x5678]) p = ffi.cast("short*", a) p2 = ffi.cast("int*", p) @@ -793,7 +795,7 @@ assert data == b'\x12\x34\x56\x78' def test_cast_pointer_and_int(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() a = ffi.new("short int[]", [0x1234, 0x5678]) l1 = ffi.cast("intptr_t", a) p = ffi.cast("short*", a) @@ -805,7 +807,7 @@ assert int(ffi.cast("intptr_t", ffi.NULL)) == 0 def test_cast_functionptr_and_int(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() def cb(n): return n + 1 a = ffi.callback("int(*)(int)", cb) @@ -817,7 +819,7 @@ assert hash(a) == hash(b) def test_callback_crash(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() def cb(n): raise Exception a = ffi.callback("int(*)(int)", cb, error=42) @@ -825,7 +827,7 @@ assert res == 42 def test_structptr_argument(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo_s { int a, b; };") def cb(p): return p[0].a * 1000 + p[0].b * 100 + p[1].a * 10 + p[1].b @@ -836,7 +838,7 @@ assert res == 5008 def test_array_argument_as_list(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo_s { int a, b; };") seen = [] def cb(argv): @@ -847,7 +849,7 @@ assert seen == [b"foobar", b"baz"] def test_cast_float(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() a = ffi.cast("float", 12) assert float(a) == 12.0 a = ffi.cast("float", 12.5) @@ -871,7 +873,7 @@ assert ffi.string(a) == b"B" def test_enum(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("enum foo { A0, B0, CC0, D0 };") assert ffi.string(ffi.cast("enum foo", 0)) == "A0" assert ffi.string(ffi.cast("enum foo", 2)) == "CC0" @@ -893,7 +895,7 @@ assert ffi.string(ffi.cast("enum baz", 0x2000)) == "B2" def test_enum_in_struct(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("enum foo { A, B, C, D }; struct bar { enum foo e; };") s = ffi.new("struct bar *") s.e = 0 @@ -914,7 +916,7 @@ py.test.raises(TypeError, "s.e = '#7'") def test_enum_non_contiguous(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("enum foo { A, B=42, C };") assert ffi.string(ffi.cast("enum foo", 0)) == "A" assert ffi.string(ffi.cast("enum foo", 42)) == "B" @@ -924,7 +926,7 @@ assert ffi.string(invalid_value) == "2" def test_enum_char_hex_oct(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef(r"enum foo{A='!', B='\'', C=0x10, D=010, E=- 0x10, F=-010};") assert ffi.string(ffi.cast("enum foo", ord('!'))) == "A" assert ffi.string(ffi.cast("enum foo", ord("'"))) == "B" @@ -934,7 +936,7 @@ assert ffi.string(ffi.cast("enum foo", -8)) == "F" def test_enum_partial(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef(r"enum foo {A, ...}; enum bar { B, C };") lib = ffi.dlopen(None) assert lib.B == 0 @@ -942,7 +944,7 @@ assert lib.C == 1 def test_array_of_struct(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo { int a, b; };") s = ffi.new("struct foo[1]") py.test.raises(AttributeError, 's.b') @@ -952,12 +954,12 @@ py.test.raises(IndexError, 's[1]') def test_pointer_to_array(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() p = ffi.new("int(**)[5]") assert repr(p) == "<cdata 'int(* *)[5]' owning %d bytes>" % SIZE_OF_PTR def test_iterate_array(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() a = ffi.new("char[]", b"hello") assert list(a) == [b"h", b"e", b"l", b"l", b"o", b"\0"] assert list(iter(a)) == [b"h", b"e", b"l", b"l", b"o", b"\0"] @@ -968,14 +970,14 @@ py.test.raises(TypeError, list, ffi.new("int *")) def test_offsetof(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo { int a, b, c; };") assert ffi.offsetof("struct foo", "a") == 0 assert ffi.offsetof("struct foo", "b") == 4 assert ffi.offsetof("struct foo", "c") == 8 def test_offsetof_nested(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo { int a, b, c; };" "struct bar { struct foo d, e; };") assert ffi.offsetof("struct bar", "e") == 12 @@ -985,7 +987,7 @@ assert ffi.offsetof("struct bar", "e", "c") == 20 def test_offsetof_array(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() assert ffi.offsetof("int[]", 51) == 51 * ffi.sizeof("int") assert ffi.offsetof("int *", 51) == 51 * ffi.sizeof("int") ffi.cdef("struct bar { int a, b; int c[99]; };") @@ -994,14 +996,14 @@ assert ffi.offsetof("struct bar", "c", 51) == 53 * ffi.sizeof("int") def test_alignof(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo { char a; short b; char c; };") assert ffi.alignof("int") == 4 assert ffi.alignof("double") in (4, 8) assert ffi.alignof("struct foo") == 2 def test_bitfield(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo { int a:10, b:20, c:3; };") assert ffi.sizeof("struct foo") == 8 s = ffi.new("struct foo *") @@ -1021,7 +1023,7 @@ assert s.c == -4 def test_bitfield_enum(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef(""" typedef enum { AA, BB, CC } foo_e; typedef struct { foo_e f:2; } foo_s; @@ -1031,7 +1033,7 @@ assert s.f == 2 def test_anonymous_struct(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("typedef struct { int a; } foo_t;") ffi.cdef("typedef struct { char b, c; } bar_t;") f = ffi.new("foo_t *", [12345]) @@ -1043,13 +1045,13 @@ def test_struct_with_two_usages(self): for name in ['foo_s', '']: # anonymous or not - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("typedef struct %s { int a; } foo_t, *foo_p;" % name) f = ffi.new("foo_t *", [12345]) ps = ffi.new("foo_p[]", [f]) def test_pointer_arithmetic(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() s = ffi.new("short[]", list(range(100, 110))) p = ffi.cast("short *", s) assert p[2] == 102 @@ -1063,7 +1065,7 @@ assert p+1 == s+1 def test_pointer_comparison(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() s = ffi.new("short[]", list(range(100))) p = ffi.cast("short *", s) assert (p < s) is False @@ -1114,7 +1116,7 @@ assert (q != None) is True def test_no_integer_comparison(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() x = ffi.cast("int", 123) y = ffi.cast("int", 456) py.test.raises(TypeError, "x < y") @@ -1124,7 +1126,7 @@ py.test.raises(TypeError, "z < y") def test_ffi_buffer_ptr(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() a = ffi.new("short *", 100) try: b = ffi.buffer(a) @@ -1143,7 +1145,7 @@ assert a[0] == 101 def test_ffi_buffer_array(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() a = ffi.new("int[]", list(range(100, 110))) try: b = ffi.buffer(a) @@ -1160,7 +1162,7 @@ assert a[1] == 0x45 def test_ffi_buffer_ptr_size(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() a = ffi.new("short *", 0x4243) try: b = ffi.buffer(a, 1) @@ -1178,7 +1180,7 @@ assert a[0] == 0x6343 def test_ffi_buffer_array_size(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() a1 = ffi.new("int[]", list(range(100, 110))) a2 = ffi.new("int[]", list(range(100, 115))) try: @@ -1188,7 +1190,7 @@ assert ffi.buffer(a1)[:] == ffi.buffer(a2, 4*10)[:] def test_ffi_buffer_with_file(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() import tempfile, os, array fd, filename = tempfile.mkstemp() f = os.fdopen(fd, 'r+b') @@ -1208,7 +1210,7 @@ os.unlink(filename) def test_ffi_buffer_with_io(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() import io, array f = io.BytesIO() a = ffi.new("int[]", list(range(1005))) @@ -1226,7 +1228,7 @@ f.close() def test_array_in_struct(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo_s { int len; short data[5]; };") p = ffi.new("struct foo_s *") p.data[3] = 5 @@ -1234,7 +1236,7 @@ assert repr(p.data).startswith("<cdata 'short[5]' 0x") def test_struct_containing_array_varsize_workaround(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo_s { int len; short data[0]; };") p = ffi.new("char[]", ffi.sizeof("struct foo_s") + 7 * SIZE_OF_SHORT) q = ffi.cast("struct foo_s *", p) @@ -1247,7 +1249,7 @@ def test_new_struct_containing_array_varsize(self): py.test.skip("later?") - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("struct foo_s { int len; short data[]; };") p = ffi.new("struct foo_s *", 10) # a single integer is the length assert p.len == 0 @@ -1255,7 +1257,7 @@ py.test.raises(IndexError, "p.data[10]") def test_ffi_typeof_getcname(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() assert ffi.getctype("int") == "int" assert ffi.getctype("int", 'x') == "int x" assert ffi.getctype("int*") == "int *" @@ -1273,7 +1275,7 @@ assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]" def test_array_of_func_ptr(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() f = ffi.cast("int(*)(int)", 42) assert f != ffi.NULL py.test.raises(CDefError, ffi.cast, "int(int)", 42) @@ -1294,7 +1296,7 @@ def test_callback_as_function_argument(self): # In C, function arguments can be declared with a function type, # which is automatically replaced with the ptr-to-function type. - ffi = FFI(backend=self.Backend()) + ffi = FFI() def cb(a, b): return chr(ord(a) + ord(b)).encode() f = ffi.callback("char cb(char, char)", cb) @@ -1306,7 +1308,7 @@ def test_vararg_callback(self): py.test.skip("callback with '...'") - ffi = FFI(backend=self.Backend()) + ffi = FFI() def cb(i, va_list): j = ffi.va_arg(va_list, "int") k = ffi.va_arg(va_list, "long long") @@ -1316,7 +1318,7 @@ assert res == 20 + 300 + 5000 def test_callback_decorator(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() # @ffi.callback("long(long, long)", error=42) def cb(a, b): @@ -1327,8 +1329,8 @@ assert cb((1 << (sz*8-1)) - 1, -10) == 42 def test_unique_types(self): - ffi1 = FFI(backend=self.Backend()) - ffi2 = FFI(backend=self.Backend()) + ffi1 = FFI() + ffi2 = FFI() assert ffi1.typeof("char") is ffi2.typeof("char ") assert ffi1.typeof("long") is ffi2.typeof("signed long int") assert ffi1.typeof("double *") is ffi2.typeof("double*") @@ -1347,7 +1349,7 @@ assert ffi1.typeof("struct foo*") is ffi1.typeof("struct foo *") def test_anonymous_enum(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("typedef enum { Value0 = 0 } e, *pe;\n" "typedef enum { Value1 = 1 } e1;") assert ffi.getctype("e*") == 'e *' @@ -1355,7 +1357,7 @@ assert ffi.getctype("e1*") == 'e1 *' def test_opaque_enum(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() ffi.cdef("enum foo;") from cffi import __version_info__ if __version_info__ < (1, 8): @@ -1366,20 +1368,20 @@ "which integer type it is meant to be (unsigned/signed, int/long)") def test_new_ctype(self): - ffi = FFI(backend=self.Backend()) + ffi = FFI() p = ffi.new("int *") py.test.raises(TypeError, ffi.new, p) p = ffi.new(ffi.typeof("int *"), 42) assert p[0] == 42 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit