Commits

Armin Rigo  committed 087f701

Fix(?) the ctypes backend, as far as the tests are concerned.

  • Participants
  • Parent commits 25c66b2

Comments (0)

Files changed (4)

File cffi/backend_ctypes.py

         raise TypeError
 
     @classmethod
-    def _arg_to_ctypes(cls, value):
+    def _arg_to_ctypes(cls, *value):
         try:
             ctype = cls._ctype
         except AttributeError:
             raise TypeError("cannot create an instance of %r" % (cls,))
-        res = cls._to_ctypes(value)
-        if not isinstance(res, ctype):
-            res = cls._ctype(res)
+        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):
-        return cls._arg_to_ctypes(init)
+        if init is None:
+            return cls._arg_to_ctypes()
+        else:
+            return cls._arg_to_ctypes(init)
 
     @staticmethod
     def _from_ctypes(ctypes_value):
         cls.__module__ = 'ffi'
 
     def _get_own_repr(self):
-        return ''
+        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)
+        return '<cdata %r %s>' % (c_name or self._get_c_name(), own)
 
     def _convert_to_address(self, BClass):
         if BClass is None:
             if isinstance(other, CTypesData):
                 return cmpfunc(self._convert_to_address(None),
                                other._convert_to_address(None))
-            elif other is None:
-                return cmpfunc(self._convert_to_address(None), 0)
             else:
                 return NotImplemented
         cmp.func_name = name
     def __hash__(self):
         return object.__hash__(self)
 
+    def _get_own_repr(self):
+        return repr(self._from_ctypes(self._value))
+
 
 class CTypesGenericArray(CTypesData):
     __slots__ = []
         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']
         self._as_ctype_ptr = ctypes.cast(address, cls._ctype)
         return self
 
+    def _get_own_repr(self):
+        return self._addr_repr(self._address)
+
     def _cast_to_integer(self):
         return self._address
 
 
     @classmethod
     def _to_ctypes(cls, value):
-        if value is None:
-            address = 0
-        else:
-            address = value._convert_to_address(cls)
+        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):
-        if not ctypes_ptr:
-            return None
         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 is not None:
+        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:
+        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)
         # 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 _get_own_repr(self):
                 if getattr(self, '_own', False):
-                    return ' owning %d bytes' % (
+                    return 'owning %d bytes' % (
                         ctypes.sizeof(self._as_ctype_ptr.contents),)
-                return ''
+                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'))):
 
             def _get_own_repr(self):
                 if getattr(self, '_own', False):
-                    return ' owning %d bytes' % (ctypes.sizeof(self._blob),)
-                return ''
+                    return 'owning %d bytes' % (ctypes.sizeof(self._blob),)
+                return super(CTypesPtr, self)._get_own_repr()
 
             def _convert_to_address(self, BClass):
                 if BClass in (CTypesPtr, None) or BClass._automatic_casts:
 
             def _get_own_repr(self):
                 if getattr(self, '_own_callback', None) is not None:
-                    return ' calling %r' % (self._own_callback,)
-                return ''
+                    return 'calling %r' % (self._own_callback,)
+                return super(CTypesFunction, self)._get_own_repr()
 
             def __call__(self, *args):
                 if has_varargs:

File testing/test_function.py

         fptr = ffi.C.puts
         assert ffi.typeof(fptr) == ffi.typeof("int(*)(const char*)")
         if self.Backend is CTypesBackend:
-            assert repr(fptr) == "<cdata 'int puts(char *)'>"
+            assert repr(fptr).startswith("<cdata 'int puts(char *)' 0x")
 
     def test_function_pointer(self):
         ffi = FFI(backend=self.Backend())

File testing/test_parsing.py

     def new_array_type(self, ptrtype, length):
         return '<array %s x %s>' % (ptrtype, length)
 
+    def new_void_type(self):
+        return "<void>"
+    def cast(self, x, y):
+        return 'casted!'
+
 class FakeStruct(object):
     def __init__(self, name):
         self.name = name

File testing/test_verify.py

         assert lib.foo(42) == 43
         assert lib.foo(44L) == 45
         assert lib.foo(ffi.cast(typename, 46)) == 47
-        py.test.raises(TypeError, lib.foo, None)
+        py.test.raises(TypeError, lib.foo, ffi.NULL)
         #
         # check for overflow cases
         if typename in all_float_types:
     ffi = FFI()
     ffi.cdef("int *foo(int *);")
     lib = ffi.verify("int *foo(int *a) { return a; }")
-    assert lib.foo(None) is None
+    assert lib.foo(ffi.NULL) == ffi.NULL
     p = ffi.new("int", 42)
     q = ffi.new("int", 42)
     assert lib.foo(p) == p
     ffi.cdef("typedef struct foo_s foo_t; int bar(foo_t *);")
     lib = ffi.verify("typedef struct foo_s foo_t;\n"
                      "int bar(foo_t *f) { return 42; }\n")
-    assert lib.bar(None) == 42
+    assert lib.bar(ffi.NULL) == 42
 
 def test_ffi_full_struct():
     ffi = FFI()
     tk = ffi.cast("token_t *", tkmem)
     results = [lib.foo(tk) for i in range(6)]
     assert results == [1, 3, 4, 6, 8, 9]
-    assert lib.foo(None) == -42
+    assert lib.foo(ffi.NULL) == -42
 
 def test_unknown_type_2():
     ffi = FFI()