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