[pypy-commit] pypy ffi-backend: Progress

arigo noreply at buildbot.pypy.org
Tue Jun 26 11:27:15 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: ffi-backend
Changeset: r55827:7f7e16925c27
Date: 2012-06-25 21:45 +0200
http://bitbucket.org/pypy/pypy/changeset/7f7e16925c27/

Log:	Progress

diff --git a/pypy/module/_ffi_backend/ctypeobj.py b/pypy/module/_ffi_backend/ctypeobj.py
--- a/pypy/module/_ffi_backend/ctypeobj.py
+++ b/pypy/module/_ffi_backend/ctypeobj.py
@@ -11,6 +11,7 @@
 
 class W_CType(Wrappable):
     #_immutable_ = True    XXX newtype.complete_struct_or_union()?
+    cast_anything = False
 
     def __init__(self, space, size, name, name_position):
         self.space = space
@@ -182,6 +183,32 @@
         from pypy.module._ffi_backend import newtype
         return newtype.alignment_of_pointer
 
+    def convert_to_object(self, cdata):
+        ptrdata = rffi.cast(rffi.CCHARPP, cdata)[0]
+        if ptrdata:
+            return cdataobj.W_CData(self.space, ptrdata, self)
+        else:
+            return self.space.w_None
+
+    def convert_from_object(self, cdata, w_ob):
+        space = self.space
+        if not space.is_w(w_ob, space.w_None):
+            ob = space.interpclass_w(w_ob)
+            if not isinstance(ob, cdataobj.W_CData):
+                raise self._convert_error("compatible pointer", w_ob)
+            otherctype = ob.ctype
+            if (isinstance(otherctype, W_CTypePtrOrArray) and
+              (self.ctitem.cast_anything or self.ctitem is otherctype.ctitem)):
+                pass    # compatible types
+            else:
+                raise self._convert_error("compatible pointer", w_ob)
+
+            ptrdata = ob._cdata
+        else:
+            ptrdata = lltype.nullptr(rffi.CCHARP.TO)
+
+        rffi.cast(rffi.CCHARPP, cdata)[0] = ptrdata
+
 
 class W_CTypeArray(W_CTypePtrOrArray):
 
@@ -328,6 +355,7 @@
 
 
 class W_CTypePrimitiveChar(W_CTypePrimitive):
+    cast_anything = True
 
     def int(self, cdata):
         return self.space.wrap(ord(cdata[0]))
@@ -584,7 +612,10 @@
         space = self.space
         ob = space.interpclass_w(w_ob)
         if isinstance(ob, cdataobj.W_CData):
-            xxx
+            if ob.ctype is self and self.size >= 0:
+                llmemory.raw_memcopy(ob._cdata, cdata, self.size)
+                keepalive_until_here(ob)
+                return
 
         if (space.isinstance_w(w_ob, space.w_list) or
             space.isinstance_w(w_ob, space.w_tuple)):
@@ -617,10 +648,21 @@
     kind = "union"
 
     def convert_from_object(self, cdata, w_ob):
-        xxx
+        space = self.space
+        ob = space.interpclass_w(w_ob)
+        if isinstance(ob, cdataobj.W_CData):
+            if ob.ctype is self and self.size >= 0:
+                llmemory.raw_memcopy(ob._cdata, cdata, self.size)
+                keepalive_until_here(ob)
+                return
+        if not self.fields_list:
+            raise OperationError(space.w_ValueError,
+                                 space.wrap("empty union"))
+        self.fields_list[0].write(cdata, w_ob)
 
 
 class W_CTypeVoid(W_CType):
+    cast_anything = True
 
     def __init__(self, space):
         W_CType.__init__(self, space, -1, "void", len("void"))
diff --git a/pypy/module/_ffi_backend/test/_backend_test_c.py b/pypy/module/_ffi_backend/test/_backend_test_c.py
--- a/pypy/module/_ffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_ffi_backend/test/_backend_test_c.py
@@ -222,6 +222,21 @@
     assert str(cast(BChar, 'A')) == 'A'
     py.test.raises(TypeError, cast, BChar, 'foo')
 
+def test_reading_pointer_to_pointer():
+    BInt = new_primitive_type("int")
+    BIntPtr = new_pointer_type(BInt)
+    BIntPtrPtr = new_pointer_type(BIntPtr)
+    q = newp(BIntPtr, 42)
+    assert q[0] == 42
+    p = newp(BIntPtrPtr, None)
+    assert p[0] is None
+    p[0] = q
+    assert p[0][0] == 42
+    q[0] += 1
+    assert p[0][0] == 43
+    p = newp(BIntPtrPtr, q)
+    assert p[0][0] == 43
+
 def test_hash_differences():
     BChar = new_primitive_type("char")
     BInt = new_primitive_type("int")
@@ -543,6 +558,15 @@
     py.test.raises(AttributeError, "p.foobar")
     py.test.raises(AttributeError, "s.foobar")
 
+def test_union_instance():
+    BInt = new_primitive_type("int")
+    BUInt = new_primitive_type("unsigned int")
+    BUnion = new_union_type("bar")
+    complete_struct_or_union(BUnion, [('a1', BInt, -1), ('a2', BUInt, -1)])
+    p = newp(new_pointer_type(BUnion), -42)
+    assert p.a1 == -42
+    assert p.a2 == -42 + (1 << (8*size_of_int()))
+
 def test_struct_pointer():
     BInt = new_primitive_type("int")
     BStruct = new_struct_type("foo")
@@ -954,12 +978,41 @@
     py.test.raises(OverflowError, newp, new_pointer_type(BUInt), -1)
     py.test.raises(OverflowError, newp, new_pointer_type(BUInt), 2**32)
 
-def test_newp_copying_struct_and_union():
+def test_newp_copying():
+    """Test that we can do newp(<type>, <cdata of the given type>) for most
+    types, with the exception of arrays, like in C.
+    """
     BInt = new_primitive_type("int")
+    p = newp(new_pointer_type(BInt), cast(BInt, 42))
+    assert p[0] == 42
+    #
+    BUInt = new_primitive_type("unsigned int")
+    p = newp(new_pointer_type(BUInt), cast(BUInt, 42))
+    assert p[0] == 42
+    #
+    BChar = new_primitive_type("char")
+    p = newp(new_pointer_type(BChar), cast(BChar, '!'))
+    assert p[0] == '!'
+    #
+    BFloat = new_primitive_type("float")
+    p = newp(new_pointer_type(BFloat), cast(BFloat, 12.25))
+    assert p[0] == 12.25
+    #
     BStruct = new_struct_type("foo_s")
     BStructPtr = new_pointer_type(BStruct)
     complete_struct_or_union(BStruct, [('a1', BInt, -1)])
     s1 = newp(BStructPtr, [42])
+    p1 = newp(new_pointer_type(BStructPtr), s1)
+    assert p1[0] == s1
+    #
+    BArray = new_array_type(new_pointer_type(BInt), None)
+    a1 = newp(BArray, [1, 2, 3, 4])
+    py.test.raises(TypeError, newp, BArray, a1)
+    BArray6 = new_array_type(new_pointer_type(BInt), 6)
+    a1 = newp(BArray6, None)
+    py.test.raises(TypeError, newp, BArray6, a1)
+    #
+    s1 = newp(BStructPtr, [42])
     s2 = newp(BStructPtr, s1[0])
     assert s2.a1 == 42
     #
@@ -969,6 +1022,11 @@
     u1 = newp(BUnionPtr, 42)
     u2 = newp(BUnionPtr, u1[0])
     assert u2.a1 == 42
+    #
+    BFunc = new_function_type((BInt,), BUInt)
+    p1 = cast(BFunc, 42)
+    p2 = newp(new_pointer_type(BFunc), p1)
+    assert p2[0] == p1
 
 def test_str():
     BChar = new_primitive_type("char")
@@ -979,3 +1037,10 @@
     assert str(a) == "hello"
     p = a + 2
     assert str(p) == "llo"
+
+def test_bug_convert_to_ptr():
+    BChar = new_primitive_type("char")
+    BCharP = new_pointer_type(BChar)
+    BDouble = new_primitive_type("double")
+    x = cast(BDouble, 42)
+    py.test.raises(TypeError, newp, new_pointer_type(BCharP), x)


More information about the pypy-commit mailing list