[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-svn
mailing list