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

arigo at codespeak.net arigo at codespeak.net
Sat Jul 14 17:31:26 CEST 2007


Author: arigo
Date: Sat Jul 14 17:31:26 2007
New Revision: 45087

Modified:
   pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py
   pypy/dist/pypy/rpython/lltypesystem/rffi.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
Log:
(lac, arigo)
- support for "void*" by pretending it's the same as "char*"
- support for function pointers
- the qsort() test passes!


Modified: pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/ll2ctypes.py	Sat Jul 14 17:31:26 2007
@@ -1,7 +1,8 @@
 import sys
 import ctypes
 import ctypes.util
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rlib.objectmodel import Symbolic
 from pypy.tool.uid import fixid
 from pypy.rlib.rarithmetic import r_uint
 
@@ -120,7 +121,15 @@
         return _ctypes_cache[T]
     except KeyError:
         if isinstance(T, lltype.Ptr):
-            cls = ctypes.POINTER(get_ctypes_type(T.TO))
+            if isinstance(T.TO, lltype.FuncType):
+                argtypes = [get_ctypes_type(ARG) for ARG in T.TO.ARGS]
+                if T.TO.RESULT is lltype.Void:
+                    restype = None
+                else:
+                    restype = get_ctypes_type(T.TO.RESULT)
+                cls = ctypes.CFUNCTYPE(restype, *argtypes)
+            else:
+                cls = ctypes.POINTER(get_ctypes_type(T.TO))
         elif isinstance(T, lltype.Struct):
             cls = build_ctypes_struct(T)
         elif isinstance(T, lltype.Array):
@@ -190,6 +199,24 @@
     T = lltype.typeOf(llobj)
     if isinstance(T, lltype.Ptr):
         container = llobj._obj
+        if isinstance(T.TO, lltype.FuncType):
+            if not hasattr(container, '_callable'):
+                raise NotImplementedError("ctypes wrapper for ll function "
+                                          "without a _callable")
+            else:
+                ctypes_func_type = get_ctypes_type(T)
+                def callback(*cargs):
+                    assert len(cargs) == len(T.TO.ARGS)
+                    llargs = [ctypes2lltype(ARG, cargs)
+                              for ARG, cargs in zip(T.TO.ARGS, cargs)]
+                    llres = container._callable(*llargs)
+                    assert lltype.typeOf(llres) == T.TO.RESULT
+                    if T.TO.RESULT is lltype.Void:
+                        return None
+                    else:
+                        return lltype2ctypes(llres)
+                return ctypes_func_type(callback)
+
         if container._ctypes_storage is None:
             if isinstance(T.TO, lltype.Struct):
                 convert_struct(container)
@@ -203,6 +230,12 @@
             p = ctypes.cast(p, ctypes.POINTER(storage._normalized_ctype))
         return p
 
+    if isinstance(llobj, Symbolic):
+        if isinstance(llobj, llmemory.ItemOffset):
+            llobj = ctypes.sizeof(get_ctypes_type(llobj.TYPE)) * llobj.repeat
+        else:
+            raise NotImplementedError(llobj)  # don't know about symbolic value
+
     if T is lltype.Char:
         return ord(llobj)
 
@@ -224,6 +257,10 @@
                 container._ctypes_storage = cobj.contents
             else:
                 raise NotImplementedError("array with an explicit length")
+        elif isinstance(T.TO, lltype.FuncType):
+            funcptr = lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'))
+            make_callable_via_ctypes(funcptr, cfunc=cobj)
+            return funcptr
         else:
             raise NotImplementedError(T)
         llobj = lltype._ptr(T, container, solid=True)
@@ -285,9 +322,10 @@
         cfunc.restype = get_ctypes_type(FUNCTYPE.RESULT)
     return cfunc
 
-def make_callable_via_ctypes(funcptr):
+def make_callable_via_ctypes(funcptr, cfunc=None):
     try:
-        cfunc = get_ctypes_callable(funcptr)
+        if cfunc is None:
+            cfunc = get_ctypes_callable(funcptr)
     except NotImplementedError, e:
         def invoke_via_ctypes(*argvalues):
             raise NotImplementedError, e
@@ -298,3 +336,10 @@
             cres = cfunc(*cargs)
             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)

Modified: pypy/dist/pypy/rpython/lltypesystem/rffi.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rffi.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rffi.py	Sat Jul 14 17:31:26 2007
@@ -1,6 +1,7 @@
 
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.lltypesystem.lloperation import llop
+from pypy.rpython.lltypesystem import ll2ctypes
 from pypy.annotation.model import lltype_to_annotation
 from pypy.rlib.objectmodel import Symbolic, CDefinedIntSymbolic
 from pypy.rlib import rarithmetic
@@ -28,7 +29,6 @@
                                  include_dirs=tuple(include_dirs),
                                  _callable=_callable)
     if _callable is None:
-        from pypy.rpython.lltypesystem import ll2ctypes
         ll2ctypes.make_callable_via_ctypes(funcptr)
     return funcptr
 
@@ -66,8 +66,8 @@
 
 c_errno = CConstant('errno', lltype.Signed)
 
-# void *
-VOIDP = lltype.Ptr(lltype.FixedSizeArray(lltype.Void, 1))
+# void *   - for now, represented as char *
+VOIDP = lltype.Ptr(lltype.Array(lltype.Char, hints={'nolength': True}))
 
 # char *
 CCHARP = lltype.Ptr(lltype.Array(lltype.Char, hints={'nolength': True}))
@@ -119,3 +119,5 @@
         free_charp(ref[i])
         i += 1
     lltype.free(ref, flavor='raw')
+
+force_cast = ll2ctypes.force_cast     # cast a ptr to another with no typecheck

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	Sat Jul 14 17:31:26 2007
@@ -1,8 +1,10 @@
 import py
-import sys
+import sys, struct
 import ctypes
-from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rpython.lltypesystem import lltype, rffi, llmemory
 from pypy.rpython.lltypesystem.ll2ctypes import lltype2ctypes, ctypes2lltype
+from pypy.rpython.lltypesystem.ll2ctypes import standard_c_lib
+from pypy.rpython.annlowlevel import llhelper
 from pypy.rlib.rarithmetic import r_uint
 
 
@@ -19,6 +21,12 @@
     res = ctypes2lltype(lltype.Unsigned, sys.maxint * 2 + 1)
     assert (res, type(res)) == (r_uint(-1), r_uint)
 
+    res = lltype2ctypes(llmemory.sizeof(lltype.Signed))
+    assert res == struct.calcsize("l")
+    S = lltype.Struct('S', ('x', lltype.Signed), ('y', lltype.Signed))
+    res = lltype2ctypes(llmemory.sizeof(S))
+    assert res == struct.calcsize("ll")
+
 def test_simple_struct():
     S = lltype.Struct('S', ('x', lltype.Signed), ('y', lltype.Signed))
     s = lltype.malloc(S, flavor='raw')
@@ -209,5 +217,99 @@
     assert res2 == res2b
     assert res3 == res3b
 
-# def test_qsort():...
+def test_force_cast():
+    import array
+    A = lltype.Array(lltype.Signed, hints={'nolength': True})
+    B = lltype.Array(lltype.Char, hints={'nolength': True})
+    a = lltype.malloc(A, 10, flavor='raw')
+    for i in range(10):
+        a[i] = i*i
+
+    b = rffi.force_cast(lltype.Ptr(B), a)
+
+    checker = array.array('l')
+    for i in range(10):
+        checker.append(i*i)
+    expected = checker.tostring()
+
+    for i in range(len(expected)):
+        assert b[i] == expected[i]
+
+    c = rffi.force_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)
+    for i in range(10):
+        assert e[i] == i*i
+
+    lltype.free(a, flavor='raw')
+
+def test_funcptr1():
+    def dummy(n):
+        return n+1
+
+    FUNCTYPE = lltype.FuncType([lltype.Signed], lltype.Signed)
+    cdummy = lltype2ctypes(llhelper(lltype.Ptr(FUNCTYPE), dummy))
+    assert isinstance(cdummy, ctypes.CFUNCTYPE(ctypes.c_long, ctypes.c_long))
+    res = cdummy(41)
+    assert res == 42
+    lldummy = ctypes2lltype(lltype.Ptr(FUNCTYPE), cdummy)
+    assert lltype.typeOf(lldummy) == lltype.Ptr(FUNCTYPE)
+    res = lldummy(41)
+    assert res == 42
+
+def test_funcptr2():
+    FUNCTYPE = lltype.FuncType([rffi.CCHARP], lltype.Signed)
+    cstrlen = standard_c_lib.strlen
+    llstrlen = ctypes2lltype(lltype.Ptr(FUNCTYPE), cstrlen)
+    assert lltype.typeOf(llstrlen) == lltype.Ptr(FUNCTYPE)
+    p = rffi.str2charp("hi there")
+    res = llstrlen(p)
+    assert res == 8
+    cstrlen2 = lltype2ctypes(llstrlen)
+    cp = lltype2ctypes(p)
+    assert cstrlen2.restype == ctypes.c_long
+    res = cstrlen2(cp)
+    assert res == 8
+    rffi.free_charp(p)
+
+def test_qsort():
+    # XXX Signed => size_t
+    CMPFUNC = lltype.FuncType([rffi.VOIDP, rffi.VOIDP], lltype.Signed)
+    qsort = rffi.llexternal('qsort', [rffi.VOIDP,
+                                      lltype.Signed,
+                                      lltype.Signed,
+                                      lltype.Ptr(CMPFUNC)],
+                            lltype.Void)
+
+    lst = [23, 43, 24, 324, 242, 34, 78, 5, 3, 10]
+    A = lltype.Array(lltype.Signed, hints={'nolength': True})
+    a = lltype.malloc(A, 10, flavor='raw')
+    for i in range(10):
+        a[i] = lst[i]
+
+    INTPTR = lltype.Ptr(lltype.FixedSizeArray(lltype.Signed, 1))
+
+    def my_compar(p1, p2):
+        p1 = rffi.force_cast(INTPTR, p1)
+        p2 = rffi.force_cast(INTPTR, 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),
+          llhelper(lltype.Ptr(CMPFUNC), my_compar))
+
+    for i in range(10):
+        print a[i],
+    print
+    lst.sort()
+    for i in range(10):
+        assert a[i] == lst[i]
+    lltype.free(a, flavor='raw')
+
 # def test_signal():...



More information about the Pypy-commit mailing list