[pypy-svn] r50829 - in pypy/dist/pypy/module/_rawffi: . test

fijal at codespeak.net fijal at codespeak.net
Mon Jan 21 13:17:07 CET 2008


Author: fijal
Date: Mon Jan 21 13:17:07 2008
New Revision: 50829

Modified:
   pypy/dist/pypy/module/_rawffi/__init__.py
   pypy/dist/pypy/module/_rawffi/callback.py
   pypy/dist/pypy/module/_rawffi/test/test__rawffi.py
Log:
Support for _rawffi callbacks (not sure how keepalive stuff will
look like, for now it's a bit crappy)


Modified: pypy/dist/pypy/module/_rawffi/__init__.py
==============================================================================
--- pypy/dist/pypy/module/_rawffi/__init__.py	(original)
+++ pypy/dist/pypy/module/_rawffi/__init__.py	Mon Jan 21 13:17:07 2008
@@ -19,7 +19,7 @@
         'sizeof'             : 'interp_rawffi.sizeof',
         'alignment'          : 'interp_rawffi.alignment',
         'charp2string'       : 'interp_rawffi.charp2string',
-        #'CallbackPtr'        : 'callback.W_CallbackPtr',
+        'CallbackPtr'        : 'callback.W_CallbackPtr',
     }
 
     appleveldefs = {

Modified: pypy/dist/pypy/module/_rawffi/callback.py
==============================================================================
--- pypy/dist/pypy/module/_rawffi/callback.py	(original)
+++ pypy/dist/pypy/module/_rawffi/callback.py	Mon Jan 21 13:17:07 2008
@@ -5,27 +5,62 @@
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.module._rawffi.structure import unpack_fields
+from pypy.module._rawffi.array import get_elem
+from pypy.module._rawffi.interp_rawffi import W_DataInstance, _get_type_,\
+     wrap_value, unwrap_value, unwrap_truncate_int
+from pypy.rlib.libffi import USERDATA_P, CallbackFuncPtr
 
-def stuff(a, b):
-    print "comparing"
-    return int(a > b)
+def callback(ll_args, ll_res, ll_userdata):
+    userdata = rffi.cast(USERDATA_P, ll_userdata)
+    callback_ptr = W_CallbackPtr.CallbackPtr_by_number[userdata.addarg]
+    w_callable = callback_ptr.w_callable
+    res = rffi.cast(rffi.VOIDPP, ll_res)
+    argtypes = callback_ptr.args
+    space = callback_ptr.space
+    w_args = space.newlist([wrap_value(space, get_elem, ll_args[i], 0,
+                                       (argtypes[i], None, None))
+                            for i in range(len(argtypes))])
+    w_res = space.call(w_callable, w_args)
+    if space.is_w(w_res, space.w_None):
+        res[0] = lltype.nullptr(rffi.VOIDP.TO)
+    else:
+        instance = space.interpclass_w(w_res)
+        if isinstance(instance, W_DataInstance):
+            res[0] = instance.ll_buffer
+        else:
+            res[0] = unwrap_truncate_int(rffi.VOIDP, space, w_res)
 
-class W_CallbackPtr(Wrappable):
+class W_CallbackPtr(W_DataInstance):
+    # XXX some weird hackery to be able to recover W_CallbackPtr object
+    #     out of number
+    CallbackPtr_by_number = {}
+    CallbackPtr_id = 0
+    
     def __init__(self, space, w_callable, w_args, w_result):
+        number = self.CallbackPtr_id
+        self.CallbackPtr_id += 1
+        self.CallbackPtr_by_number[number] = self
+        self.space = space
         self.w_callable = w_callable
+        self.number = number
         self.args = [space.str_w(w_arg) for w_arg in space.unpackiterable(
             w_args)]
+        self.result = space.str_w(w_result)
+        ffiargs = [_get_type_(space, arg) for arg in self.args]
+        ffiresult = _get_type_(space, self.result)
+        # necessary to keep stuff alive
+        self.ll_callback = CallbackFuncPtr(ffiargs, ffiresult,
+                                           callback, number)
+        self.ll_buffer = self.ll_callback.ll_closure
 
-    def getllfuncptr(space, self):
-        TP = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed)
-        ptr = lltype.functionptr(TP, stuff)
-        return space.wrap(rffi.cast(rffi.Unsigned, ptr))
+    def __del__(self):
+        del self.CallbackPtr_by_number[self.number]
 
 def descr_new_callbackptr(space, w_type, w_callable, w_args, w_result):
     return W_CallbackPtr(space, w_callable, w_args, w_result)
 
 W_CallbackPtr.typedef = TypeDef(
     'CallbackPtr',
-    buffer  = GetSetProperty(W_CallbackPtr.getllfuncptr),
     __new__ = interp2app(descr_new_callbackptr),
+    byptr   = interp2app(W_CallbackPtr.byptr),
 )

Modified: pypy/dist/pypy/module/_rawffi/test/test__rawffi.py
==============================================================================
--- pypy/dist/pypy/module/_rawffi/test/test__rawffi.py	(original)
+++ pypy/dist/pypy/module/_rawffi/test/test__rawffi.py	Mon Jan 21 13:17:07 2008
@@ -359,18 +359,32 @@
         arg1.free()
     
     def test_callback(self):
-        skip("Not working")
         import _rawffi
+        import struct
         libc = _rawffi.CDLL('libc.so.6')
-        to_sort = "kljhgfa"
-        ll_to_sort = _rawffi.Array('c')(to_sort)
+        ll_to_sort = _rawffi.Array('i')(4)
+        for i in range(4):
+            ll_to_sort[i] = 4-i
         qsort = libc.ptr('qsort', ['P', 'i', 'i', 'P'], None)
+        resarray = _rawffi.Array('i')(1)
         def compare(a, b):
-            return a < b
-        qsort(ll_to_sort, len(to_sort), 1,
-              _rawffi.CallbackPtr(compare, ['i', 'i'], 'i'))
-        res = [ll_to_sort[i] for i in range(len(to_sort))]
-        assert res == sorted(to_sort)
+            a1 = _rawffi.Array('i').fromaddress(a, 1)
+            a2 = _rawffi.Array('i').fromaddress(b, 1)
+            if a1[0] > a2[0]:
+                res = 1
+            res = -1
+            resarray[0] = res
+            return resarray
+        a1 = ll_to_sort.byptr()
+        a2 = _rawffi.Array('i')(1)
+        a2[0] = len(ll_to_sort)
+        a3 = _rawffi.Array('i')(1)
+        a3[0] = struct.calcsize('i')
+        cb = _rawffi.CallbackPtr(compare, ['P', 'P'], 'i')
+        a4 = cb.byptr()
+        qsort(a1, a2, a3, a4)
+        res = [ll_to_sort[i] for i in range(len(ll_to_sort))]
+        assert res == [1,2,3,4]
 
     def test_setattr_struct(self):
         import _rawffi



More information about the Pypy-commit mailing list