[pypy-svn] pypy jitypes2: add the possibility to pass random objects as pointers, as long as they implement the _as_ffi_pointer() method

antocuni commits-noreply at bitbucket.org
Fri Jan 28 11:32:15 CET 2011


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: jitypes2
Changeset: r41420:a2e384f73c04
Date: 2011-01-28 11:31 +0100
http://bitbucket.org/pypy/pypy/changeset/a2e384f73c04/

Log:	add the possibility to pass random objects as pointers, as long as
	they implement the _as_ffi_pointer() method

diff --git a/pypy/module/_ffi/test/test__ffi.py b/pypy/module/_ffi/test/test__ffi.py
--- a/pypy/module/_ffi/test/test__ffi.py
+++ b/pypy/module/_ffi/test/test__ffi.py
@@ -158,6 +158,35 @@
         assert get_dummy() == 123
         set_val_to_ptr(ptr, 0)
 
+    def test_convert_pointer_args(self):
+        """
+            extern int dummy; // defined in test_void_result 
+            DLLEXPORT int* get_dummy_ptr(); // defined in test_pointer_args
+            DLLEXPORT void set_val_to_ptr(int* ptr, int val); // ditto
+        """
+        from _ffi import CDLL, types
+
+        class MyPointerWrapper(object):
+            def __init__(self, value):
+                self.value = value
+            def _as_ffi_pointer_(self):
+                return self.value
+        
+        libfoo = CDLL(self.libfoo_name)
+        get_dummy = libfoo.getfunc('get_dummy', [], types.sint)
+        get_dummy_ptr = libfoo.getfunc('get_dummy_ptr', [], types.pointer)
+        set_val_to_ptr = libfoo.getfunc('set_val_to_ptr',
+                                        [types.pointer, types.sint],
+                                        types.void)
+        assert get_dummy() == 0
+        ptr = get_dummy_ptr()
+        assert type(ptr) in (int, long)
+        ptr2 = MyPointerWrapper(ptr)
+        set_val_to_ptr(ptr2, 123)
+        assert get_dummy() == 123
+        set_val_to_ptr(ptr2, 0)
+
+
     def test_huge_pointer_args(self):
         """
             #include <stdlib.h>

diff --git a/pypy/module/_ffi/interp_ffi.py b/pypy/module/_ffi/interp_ffi.py
--- a/pypy/module/_ffi/interp_ffi.py
+++ b/pypy/module/_ffi/interp_ffi.py
@@ -41,8 +41,10 @@
                 self is app_types.uint or
                 self is app_types.ushort or
                 self is app_types.ubyte or
-                self is app_types.ulonglong or
-                self is app_types.pointer)
+                self is app_types.ulonglong)
+
+    def is_pointer(self):
+        return self is app_types.pointer
 
     def is_char(self):
         return self is app_types.char
@@ -163,6 +165,9 @@
                 self.arg_longlong(space, argchain, kind, w_arg)
             elif w_argtype.is_signed():
                 argchain.arg(space.int_w(w_arg))
+            elif w_argtype.is_pointer():
+                w_arg = self.convert_pointer_arg_maybe(space, w_arg)
+                argchain.arg(intmask(space.uint_w(w_arg)))
             elif w_argtype.is_unsigned():
                 argchain.arg(intmask(space.uint_w(w_arg)))
             elif w_argtype.is_char():
@@ -184,6 +189,16 @@
                 assert False, "Argument shape '%s' not supported" % w_argtype
         return argchain
 
+    def convert_pointer_arg_maybe(self, space, w_arg):
+        """
+        Try to convert the argument by calling _as_ffi_pointer_()
+        """
+        meth = space.lookup(w_arg, '_as_ffi_pointer_') # this also promotes the type
+        if meth:
+            return space.call_function(meth, w_arg)
+        else:
+            return w_arg
+
     @jit.dont_look_inside
     def arg_longlong(self, space, argchain, kind, w_arg):
         bigarg = space.bigint_w(w_arg)
@@ -212,7 +227,7 @@
             return self._call_longlong(space, argchain, reskind)
         elif w_restype.is_signed():
             return self._call_int(space, argchain)
-        elif w_restype.is_unsigned():
+        elif w_restype.is_unsigned() or w_restype.is_pointer():
             return self._call_uint(space, argchain)
         elif w_restype.is_char():
             intres = self.func.call(argchain, rffi.UCHAR)


More information about the Pypy-commit mailing list