[pypy-svn] r45125 - in pypy/dist/pypy/rpython/lltypesystem: . test

arigo at codespeak.net arigo at codespeak.net
Mon Jul 16 14:01:05 CEST 2007


Author: arigo
Date: Mon Jul 16 14:01:04 2007
New Revision: 45125

Modified:
   pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py
   pypy/dist/pypy/rpython/lltypesystem/rffi.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py
Log:
Rename rffi.force_cast() to rffi.cast().  Generalize it, trying to make
it work in the same situations as a cast in C would.  Now the qsort test
passes again when the numbers are properly casted.


Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py	Mon Jul 16 14:01:04 2007
@@ -285,8 +285,14 @@
         llobj = lltype._ptr(T, container, solid=True)
     elif T is lltype.Char:
         llobj = chr(cobj)
-    elif T is lltype.Unsigned:
-        llobj = r_uint(cobj)
+    elif T is not lltype.Signed:
+        from pypy.rpython.lltypesystem import rffi
+        try:
+            inttype = rffi.numbertype_to_rclass[T]
+        except KeyError:
+            llobj = cobj
+        else:
+            llobj = inttype(cobj)
     else:
         llobj = cobj
 
@@ -370,9 +376,26 @@
             return ctypes2lltype(RESULT, cres)
     funcptr._obj._callable = invoke_via_ctypes
 
-def force_cast(PTRTYPE, ptr):
-    """Cast a pointer to another pointer with no typechecking."""
-    CPtrType = get_ctypes_type(PTRTYPE)
-    cptr = lltype2ctypes(ptr)
-    cptr = ctypes.cast(cptr, CPtrType)
-    return ctypes2lltype(PTRTYPE, cptr)
+def force_cast(RESTYPE, value):
+    """Cast a value to a result type, trying to use the same rules as C."""
+    TYPE1 = lltype.typeOf(value)
+    cvalue = lltype2ctypes(value)
+    cresulttype = get_ctypes_type(RESTYPE)
+    if isinstance(TYPE1, lltype.Ptr):
+        if isinstance(RESTYPE, lltype.Ptr):
+            # shortcut: ptr->ptr cast
+            cptr = ctypes.cast(cvalue, cresulttype)
+            return ctypes2lltype(RESTYPE, cptr)
+        # first cast the input pointer to an integer
+        cvalue = ctypes.c_void_p(cvalue).value
+    elif isinstance(cvalue, (str, unicode)):
+        cvalue = ord(cvalue)     # character -> integer
+
+    if not isinstance(cvalue, (int, long)):
+        raise NotImplementedError("casting %r to %r" % (TYPE1, RESTYPE))
+
+    if isinstance(RESTYPE, lltype.Ptr):
+        cvalue = ctypes.cast(ctypes.c_void_p(cvalue), cresulttype)
+    else:
+        cvalue = cresulttype(cvalue).value   # mask high bits off if needed
+    return ctypes2lltype(RESTYPE, cvalue)

Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rffi.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rffi.py	Mon Jul 16 14:01:04 2007
@@ -32,6 +32,8 @@
         ll2ctypes.make_callable_via_ctypes(funcptr)
     return funcptr
 
+numbertype_to_rclass = {}     # {USHORT: r_ushort, ...}
+
 def setup():
     """ creates necessary c-level types
     """
@@ -45,10 +47,13 @@
         name = name.replace(' ', '')
         llname = name.upper()
         inttype = rarithmetic.build_int('r_' + name, signed, bits)
+        NUMBERTYPE = lltype.build_number(llname, inttype)
         globals()['r_' + name] = inttype
-        globals()[llname] = lltype.build_number(llname, inttype)
+        globals()[llname] = NUMBERTYPE
+        numbertype_to_rclass[NUMBERTYPE] = inttype
 
 setup()
+numbertype_to_rclass[lltype.Signed] = int     # avoid "r_long" for common cases
 # ^^^ this creates at least the following names:
 # --------------------------------------------------------------------
 #        Type           RPython integer class doing wrap-around
@@ -143,4 +148,4 @@
         i += 1
     lltype.free(ref, flavor='raw')
 
-force_cast = ll2ctypes.force_cast     # cast a ptr to another with no typecheck
+cast = ll2ctypes.force_cast      # a forced, no-checking cast

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py	Mon Jul 16 14:01:04 2007
@@ -217,7 +217,14 @@
     assert res2 == res2b
     assert res3 == res3b
 
-def test_force_cast():
+def test_simple_cast():
+    assert rffi.cast(rffi.SIGNEDCHAR, 0x123456) == 0x56
+    assert rffi.cast(rffi.SIGNEDCHAR, 0x123481) == -127
+    assert rffi.cast(rffi.CHAR, 0x123456) == '\x56'
+    assert rffi.cast(rffi.CHAR, 0x123481) == '\x81'
+    assert rffi.cast(rffi.UCHAR, 0x123481) == 0x81
+
+def test_forced_ptr_cast():
     import array
     A = lltype.Array(lltype.Signed, hints={'nolength': True})
     B = lltype.Array(lltype.Char, hints={'nolength': True})
@@ -225,7 +232,7 @@
     for i in range(10):
         a[i] = i*i
 
-    b = rffi.force_cast(lltype.Ptr(B), a)
+    b = rffi.cast(lltype.Ptr(B), a)
 
     checker = array.array('l')
     for i in range(10):
@@ -235,13 +242,13 @@
     for i in range(len(expected)):
         assert b[i] == expected[i]
 
-    c = rffi.force_cast(rffi.VOIDP, a)
+    c = rffi.cast(rffi.VOIDP, a)
     addr = lltype2ctypes(c)
     #assert addr == ctypes.addressof(a._obj._ctypes_storage)
     d = ctypes2lltype(rffi.VOIDP, addr)
     assert lltype.typeOf(d) == rffi.VOIDP
     assert c == d
-    e = rffi.force_cast(lltype.Ptr(A), d)
+    e = rffi.cast(lltype.Ptr(A), d)
     for i in range(10):
         assert e[i] == i*i
 
@@ -277,7 +284,6 @@
     rffi.free_charp(p)
 
 def test_qsort():
-    py.test.skip("in-progress: size_t vs. Signed")
     CMPFUNC = lltype.FuncType([rffi.VOIDP, rffi.VOIDP], rffi.INT)
     qsort = rffi.llexternal('qsort', [rffi.VOIDP,
                                       rffi.SIZE_T,
@@ -294,14 +300,14 @@
     SIGNEDPTR = lltype.Ptr(lltype.FixedSizeArray(lltype.Signed, 1))
 
     def my_compar(p1, p2):
-        p1 = rffi.force_cast(SIGNEDPTR, p1)
-        p2 = rffi.force_cast(SIGNEDPTR, p2)
+        p1 = rffi.cast(SIGNEDPTR, p1)
+        p2 = rffi.cast(SIGNEDPTR, p2)
         print 'my_compar:', p1[0], p2[0]
         return cmp(p1[0], p2[0])
 
-    qsort(rffi.force_cast(rffi.VOIDP, a),
-          10,
-          llmemory.sizeof(lltype.Signed),
+    qsort(rffi.cast(rffi.VOIDP, a),
+          rffi.cast(rffi.SIZE_T, 10),
+          rffi.cast(rffi.SIZE_T, llmemory.sizeof(lltype.Signed)),
           llhelper(lltype.Ptr(CMPFUNC), my_compar))
 
     for i in range(10):

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_rffi.py	Mon Jul 16 14:01:04 2007
@@ -197,3 +197,8 @@
 
 def test_size_t_sign():
     assert r_size_t(-1) > 0
+
+def test_cast():
+    res = cast(SIZE_T, -1)
+    assert type(res) is r_size_t
+    assert res == r_size_t(-1)



More information about the Pypy-commit mailing list