[pypy-svn] pypy jitypes2: introduce 'typed pointers', which carry info on which type they are pointing to; also, pass the argtype to the _as_ffi_pointer_ method; this should allow _ctypes to do type check on pointers when converting arguments

antocuni commits-noreply at bitbucket.org
Thu Mar 24 12:22:51 CET 2011


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: jitypes2
Changeset: r42897:888a6561b67a
Date: 2011-03-24 12:22 +0100
http://bitbucket.org/pypy/pypy/changeset/888a6561b67a/

Log:	introduce 'typed pointers', which carry info on which type they are
	pointing to; also, pass the argtype to the _as_ffi_pointer_ method;
	this should allow _ctypes to do type check on pointers when
	converting arguments

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
@@ -169,7 +169,8 @@
         class MyPointerWrapper(object):
             def __init__(self, value):
                 self.value = value
-            def _as_ffi_pointer_(self):
+            def _as_ffi_pointer_(self, ffitype):
+                assert ffitype is types.pointer
                 return self.value
         
         libfoo = CDLL(self.libfoo_name)
@@ -186,6 +187,31 @@
         assert get_dummy() == 123
         set_val_to_ptr(ptr2, 0)
 
+    def test_typed_pointer(self):
+        from _ffi import types
+        intptr = types.Pointer(types.sint) # create a typed pointer to sint
+        assert intptr.deref_pointer() is types.sint
+        assert str(intptr) == '<ffi type (pointer to sint)>'
+        assert types.sint.deref_pointer() is None
+
+    def test_typed_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
+
+        libfoo = CDLL(self.libfoo_name)
+        intptr = types.Pointer(types.sint)
+        get_dummy = libfoo.getfunc('get_dummy', [], types.sint)
+        get_dummy_ptr = libfoo.getfunc('get_dummy_ptr', [], intptr)
+        set_val_to_ptr = libfoo.getfunc('set_val_to_ptr', [intptr, types.sint], types.void)
+        assert get_dummy() == 0
+        ptr = get_dummy_ptr()
+        set_val_to_ptr(ptr, 123)
+        assert get_dummy() == 123
+        set_val_to_ptr(ptr, 0)
 
     def test_huge_pointer_args(self):
         """

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
@@ -14,17 +14,23 @@
 from pypy.rlib.rarithmetic import intmask, r_uint
 
 class W_FFIType(Wrappable):
-    def __init__(self, name, ffitype, w_datashape=None):
+    def __init__(self, name, ffitype, w_datashape=None, w_pointer_to=None):
         self.name = name
         self.ffitype = ffitype
         self.w_datashape = w_datashape
+        self.w_pointer_to = w_pointer_to
         if self.is_struct():
             assert w_datashape is not None
 
-    def str(self, space):
+    def descr_deref_pointer(self, space):
+        if self.w_pointer_to is None:
+            return space.w_None
+        return self.w_pointer_to
+
+    def repr(self, space):
         return space.wrap(self.__str__())
 
-    def __str__(self):
+    def __repr__(self):
         return "<ffi type %s>" % self.name
 
     def is_signed(self):
@@ -42,7 +48,7 @@
                 self is app_types.ulonglong)
 
     def is_pointer(self):
-        return self is app_types.pointer
+        return self.ffitype is libffi.types.pointer
 
     def is_char(self):
         return self is app_types.char
@@ -68,7 +74,8 @@
 
 W_FFIType.typedef = TypeDef(
     'FFIType',
-    __str__ = interp2app(W_FFIType.str),
+    __repr__ = interp2app(W_FFIType.repr),
+    deref_pointer = interp2app(W_FFIType.descr_deref_pointer),
     )
 
 
@@ -113,10 +120,15 @@
     pass
 app_types.__dict__ = build_ffi_types()
 
+def descr_new_pointer(space, w_cls, w_pointer_to):
+    name = '(pointer to %s)' % w_pointer_to.name
+    return W_FFIType(name, libffi.types.pointer, w_pointer_to = w_pointer_to)
+
 class W_types(Wrappable):
     pass
 W_types.typedef = TypeDef(
     'types',
+    Pointer = interp2app(descr_new_pointer, as_classmethod=True),
     **app_types.__dict__)
 
 
@@ -164,7 +176,7 @@
             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)
+                w_arg = self.convert_pointer_arg_maybe(space, w_arg, w_argtype)
                 argchain.arg(intmask(space.uint_w(w_arg)))
             elif w_argtype.is_unsigned():
                 argchain.arg(intmask(space.uint_w(w_arg)))
@@ -187,13 +199,13 @@
                 assert False, "Argument shape '%s' not supported" % w_argtype
         return argchain
 
-    def convert_pointer_arg_maybe(self, space, w_arg):
+    def convert_pointer_arg_maybe(self, space, w_arg, w_argtype):
         """
         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)
+            return space.call_function(meth, w_arg, w_argtype)
         else:
             return w_arg
 


More information about the Pypy-commit mailing list