[pypy-svn] r60099 - in pypy/branch/oo-jit/pypy/rpython/lltypesystem: . test

fijal at codespeak.net fijal at codespeak.net
Sun Nov 23 21:42:44 CET 2008


Author: fijal
Date: Sun Nov 23 21:42:43 2008
New Revision: 60099

Modified:
   pypy/branch/oo-jit/pypy/rpython/lltypesystem/ll2ctypes.py
   pypy/branch/oo-jit/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
Log:
Yet Another Evil Hack to support passing around opaque objects


Modified: pypy/branch/oo-jit/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/branch/oo-jit/pypy/rpython/lltypesystem/ll2ctypes.py	(original)
+++ pypy/branch/oo-jit/pypy/rpython/lltypesystem/ll2ctypes.py	Sun Nov 23 21:42:43 2008
@@ -17,6 +17,7 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.rpython.lltypesystem.rclass import OBJECT
+from pypy.rpython.annlowlevel import base_ptr_lltype
 
 def uaddressof(obj):
     return fixid(ctypes.addressof(obj))
@@ -177,6 +178,8 @@
             return cls
 
 def build_new_ctypes_type(rtyper, T, delayed_builders):
+    if T is base_ptr_lltype():
+        return ctypes.c_void_p
     if isinstance(T, lltype.Ptr):
         if isinstance(T.TO, lltype.FuncType):
             argtypes = [get_ctypes_type(rtyper, ARG) for ARG in T.TO.ARGS
@@ -441,6 +444,24 @@
 _all_callbacks = []
 _callback2obj = {}
 
+# this is just another hack that passes around references to applevel types
+# disguised as base_ptr_lltype
+class Dummy(object):
+    pass
+
+_opaque_cache = {Dummy():0}
+_opaque_list = [Dummy()]
+
+def new_opaque_object(llobj):
+    try:
+        return _opaque_cache[llobj]
+    except KeyError:
+        assert len(_opaque_cache) == len(_opaque_list)
+        val = ctypes.cast(len(_opaque_cache), ctypes.c_void_p)
+        _opaque_list.append(llobj)
+        _opaque_cache[llobj] = val
+        return val
+
 def lltype2ctypes(llobj, rtyper, normalize=True):
     """Convert the lltype object 'llobj' to its ctypes equivalent.
     'normalize' should only be False in tests, where we want to
@@ -454,6 +475,8 @@
         if not llobj:   # NULL pointer
             return get_ctypes_type(rtyper, T)()
 
+        if T is base_ptr_lltype():
+            return new_opaque_object(llobj)
         container = llobj._obj
         if isinstance(T.TO, lltype.FuncType):
             if hasattr(container, 'graph'):
@@ -556,6 +579,8 @@
     if isinstance(T, lltype.Ptr):
         if not cobj:   # NULL pointer
             return lltype.nullptr(T.TO)
+        if T is base_ptr_lltype():
+            return _opaque_list[cobj]
         if isinstance(T.TO, lltype.Struct):
             if T.TO._arrayfld is not None:
                 carray = getattr(cobj.contents, T.TO._arrayfld)

Modified: pypy/branch/oo-jit/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
==============================================================================
--- pypy/branch/oo-jit/pypy/rpython/lltypesystem/test/test_ll2ctypes.py	(original)
+++ pypy/branch/oo-jit/pypy/rpython/lltypesystem/test/test_ll2ctypes.py	Sun Nov 23 21:42:43 2008
@@ -784,32 +784,6 @@
 
         assert f() == 6
 
-##    def test_c_callback_with_void_arg(self):
-##        class Stuff(object):
-##            def __init__(self, x):
-##                self.x = x
-
-##        c_source = py.code.Source("""
-##        int eating_callback(int arg, int voidarg, int(*call)(int, int))
-##        {
-##            return call(arg, voidarg);
-##        }
-##        """)
-
-##        eci = ExternalCompilationInfo(separate_module_sources=[c_source])
-
-##        args = [rffi.INT, rffi.INT,
-##                rffi.CCallback([rffi.INT, lltype.Void], rffi.INT)]
-
-##        def callback(x, stuff):
-##            return x + stuff.x
-        
-##        eating_callback = rffi.llexternal('eating_callback', args, rffi.INT,
-##                                          compilation_info=eci)
-
-##        v = register_void_value(Stuff(2))
-##        assert eating_callback(3, v, callback) == 3+2
-
     def test_qsort(self):
         TP = rffi.CArrayPtr(rffi.INT)
         a = lltype.malloc(TP.TO, 5, flavor='raw')
@@ -925,3 +899,30 @@
         assert op.args[0].value._obj._callable == pypy.rpython.lltypesystem.rstr.LLHelpers.ll_stritem.im_func
         assert op.args[1].value == pypy.rpython.lltypesystem.rstr.LLHelpers
         assert op.args[3].value == -2
+
+    def test_pass_around_t_object(self):
+        from pypy.rpython.annlowlevel import base_ptr_lltype
+        T = base_ptr_lltype()
+        
+        class X(object):
+            _TYPE = T
+            x = 10
+
+        def callback(x):
+            return x.x
+
+        c_source = py.code.Source("""
+        int eating_callback(void *arg, int(*call)(int))
+        {
+            return call(arg);
+        }
+        """)
+
+        eci = ExternalCompilationInfo(separate_module_sources=[c_source])
+
+        args = [T, rffi.CCallback([T], rffi.INT)]
+        eating_callback = rffi.llexternal('eating_callback', args, rffi.INT,
+                                          compilation_info=eci)
+
+        res = eating_callback(X(), callback)
+        assert res == 10



More information about the Pypy-commit mailing list