[pypy-svn] r47509 - in pypy/dist/pypy/module/_ffi: . test

fijal at codespeak.net fijal at codespeak.net
Wed Oct 17 12:33:51 CEST 2007


Author: fijal
Date: Wed Oct 17 12:33:50 2007
New Revision: 47509

Modified:
   pypy/dist/pypy/module/_ffi/TODO
   pypy/dist/pypy/module/_ffi/__init__.py
   pypy/dist/pypy/module/_ffi/app_ffi.py
   pypy/dist/pypy/module/_ffi/interp_ffi.py
   pypy/dist/pypy/module/_ffi/structure.py
   pypy/dist/pypy/module/_ffi/test/test__ffi.py
Log:
Add arrays, working almost out of the box.


Modified: pypy/dist/pypy/module/_ffi/TODO
==============================================================================
--- pypy/dist/pypy/module/_ffi/TODO	(original)
+++ pypy/dist/pypy/module/_ffi/TODO	Wed Oct 17 12:33:50 2007
@@ -2,6 +2,6 @@
 * long support with all messy corners (when to create long integer and
   such), also short overflowing
 
-* add arrays
-
+* add faulty parameters checking (they end up with fatal rpython error KeyErro
+  or sth like that by now)
 

Modified: pypy/dist/pypy/module/_ffi/__init__.py
==============================================================================
--- pypy/dist/pypy/module/_ffi/__init__.py	(original)
+++ pypy/dist/pypy/module/_ffi/__init__.py	Wed Oct 17 12:33:50 2007
@@ -12,10 +12,12 @@
     interpleveldefs = {
         'CDLL'               : 'interp_ffi.W_CDLL',
         'FuncPtr'            : 'interp_ffi.W_FuncPtr',
-        'StructureInstance' : 'structure.W_StructureInstance',
+        'StructureInstance'  : 'structure.W_StructureInstance',
+        'ArrayInstance'      : 'array.W_ArrayInstance',
     }
 
     appleveldefs = {
         'Structure'         : 'app_ffi.Structure',
+        'Array'             : 'app_ffi.Array',
         #'StructureInstance' : 'app_ffi.StructureInstance',
     }

Modified: pypy/dist/pypy/module/_ffi/app_ffi.py
==============================================================================
--- pypy/dist/pypy/module/_ffi/app_ffi.py	(original)
+++ pypy/dist/pypy/module/_ffi/app_ffi.py	Wed Oct 17 12:33:50 2007
@@ -13,3 +13,11 @@
                 raise TypeError("Keyword arguments not allowed when passing address argument")
             return StructureInstance(self, args[0], None)
         return StructureInstance(self, None, kwds)
+
+class Array(object):
+    def __init__(self, of):
+        self.of = of
+
+    def __call__(self, size):
+        from _ffi import ArrayInstance
+        return ArrayInstance(self.of, size)

Modified: pypy/dist/pypy/module/_ffi/interp_ffi.py
==============================================================================
--- pypy/dist/pypy/module/_ffi/interp_ffi.py	(original)
+++ pypy/dist/pypy/module/_ffi/interp_ffi.py	Wed Oct 17 12:33:50 2007
@@ -141,7 +141,9 @@
         else:
             mod = space.getbuiltinmodule('_ffi')
             w_StructureInstance = space.getattr(mod, w('StructureInstance'))
-            if space.is_true(space.isinstance(w_arg, w_StructureInstance)):
+            w_ArrayInstance = space.getattr(mod, w('ArrayInstance'))
+            if space.is_true(space.isinstance(w_arg, w_StructureInstance)) or\
+                   space.is_true(space.isinstance(w_arg, w_ArrayInstance)):
                 ptr = rffi.cast(rffi.VOIDP, space.int_w(space.getattr(w_arg, w('buffer'))))
                 push_func(add_arg, argdesc, ptr)
             else:
@@ -162,33 +164,37 @@
 
 ll_typemap_iter = unrolling_iterable(LL_TYPEMAP.items())
 
-def wrap_result(space, restype, arg, func):
+def wrap_result(space, restype, arg, argdesc, func):
     for c, ll_type in ll_typemap_iter:
         if restype == c:
             if c == 's':
-                ptr = func(arg, rffi.CCHARP)
+                ptr = func(arg, argdesc, rffi.CCHARP)
                 if not ptr:
                     return space.w_None
                 return space.wrap(rffi.charp2str(ptr))
             elif c == 'P':
-                res = func(arg, rffi.VOIDP)
+                res = func(arg, argdesc, rffi.VOIDP)
+                if not res:
+                    return space.w_None
                 return space.wrap(rffi.cast(rffi.INT, res))
             #elif c == 'q' or c == 'Q' or c == 'L':
             #    return space.newlong(func(arg, ll_type))
             elif c == 'f' or c == 'd':
-                return space.wrap(float(func(arg, ll_type)))
+                return space.wrap(float(func(arg, argdesc, ll_type)))
             elif c == 'c' or c == 'b' or c == 'B':
-                return space.wrap(chr(rffi.cast(rffi.INT, func(arg, ll_type))))
+                return space.wrap(chr(rffi.cast(rffi.INT, func(arg, argdesc,
+                                                               ll_type))))
             elif c == 'h' or c == 'H':
-                return space.wrap(rffi.cast(rffi.INT, func(arg, ll_type)))
+                return space.wrap(rffi.cast(rffi.INT, func(arg, argdesc,
+                                                           ll_type)))
             else:
-                return space.wrap(intmask(func(arg, ll_type)))
+                return space.wrap(intmask(func(arg, argdesc, ll_type)))
     return space.w_None
 wrap_result._annspecialcase_ = 'specialize:arg(3)'
 
-def ptr_call(ptr, ll_type):
+def ptr_call(ptr, some_arg, ll_type):
     return ptr.call(ll_type)
-ptr_call._annspecialcase_ = 'specialize:arg(1)'
+ptr_call._annspecialcase_ = 'specialize:arg(2)'
 
 def push(ptr, argdesc, value):
     ptr.push_arg(value)
@@ -214,7 +220,7 @@
             unwrap_arg(space, push, self.ptr, i, argtype, w_arg, to_free)
             i += 1
         try:
-            return wrap_result(space, self.restype, self.ptr, ptr_call)
+            return wrap_result(space, self.restype, self.ptr, None, ptr_call)
         finally:
             for elem in to_free:
                 lltype.free(elem, flavor='raw')

Modified: pypy/dist/pypy/module/_ffi/structure.py
==============================================================================
--- pypy/dist/pypy/module/_ffi/structure.py	(original)
+++ pypy/dist/pypy/module/_ffi/structure.py	Wed Oct 17 12:33:50 2007
@@ -50,12 +50,11 @@
     rffi.cast(T, ptr)[0] = value
 push_field._annspecialcase_ = 'specialize:argtype(2)'
     
-def cast_pos(self, ll_t):
-    i = self.next_pos
+def cast_pos(self, i, ll_t):
     pos = rffi.ptradd(self.ll_buffer, self.ll_positions[i])
     TP = lltype.Ptr(rffi.CArray(ll_t))
     return rffi.cast(TP, pos)[0]
-cast_pos._annspecialcase_ = 'specialize:arg(1)'
+cast_pos._annspecialcase_ = 'specialize:arg(2)'
 
 class W_StructureInstance(Wrappable):
     def __init__(self, space, w_shape, w_address, w_fieldinits):
@@ -71,7 +70,6 @@
             self.ll_buffer = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw',
                                            zero=True)
         self.ll_positions = pos
-        self.next_pos = 0
         if space.is_true(w_fieldinits):
             for w_field in space.unpackiterable(w_fieldinits):
                 w_value = space.getitem(w_fieldinits, w_field)
@@ -83,9 +81,7 @@
         for i in range(len(self.fields)):
             name, c = self.fields[i]
             if name == attr:
-                # XXX RPython-trick for passing lambda around
-                self.next_pos = i
-                return wrap_result(space, c, self, cast_pos)
+                return wrap_result(space, c, self, i, cast_pos)
         raise OperationError(space.w_AttributeError, space.wrap(
             "C Structure has no attribute %s" % attr))
     getattr.unwrap_spec = ['self', ObjSpace, str]

Modified: pypy/dist/pypy/module/_ffi/test/test__ffi.py
==============================================================================
--- pypy/dist/pypy/module/_ffi/test/test__ffi.py	(original)
+++ pypy/dist/pypy/module/_ffi/test/test__ffi.py	Wed Oct 17 12:33:50 2007
@@ -59,6 +59,16 @@
               return static_str;
            return NULL;
         }
+
+        int get_array_elem(int* stuff, int num)
+        {
+           return stuff[num];
+        }
+
+        struct x* get_array_elem_s(struct x** array, int num)
+        {
+           return array[num];
+        }
         '''))
         compile_c_module([c_file], 'x')
         return str(udir.join('x.so'))
@@ -188,6 +198,34 @@
         x = create_double_struct()
         assert X(X(x).next).x2 == 3
 
+    def test_array(self):
+        import _ffi
+        lib = _ffi.CDLL(self.lib_name)
+        A = _ffi.Array('i')
+        get_array_elem = lib.ptr('get_array_elem', ['P', 'i'], 'i')
+        a = A(10)
+        a[8] = 3
+        a[7] = 1
+        a[6] = 2
+        assert get_array_elem(a, 9) == 0
+        assert get_array_elem(a, 8) == 3
+        assert get_array_elem(a, 7) == 1
+        assert get_array_elem(a, 6) == 2
+        assert a[3] == 0
+
+    def test_array_of_structure(self):
+        import _ffi
+        lib = _ffi.CDLL(self.lib_name)
+        A = _ffi.Array('P')
+        X = _ffi.Structure([('x1', 'i'), ('x2', 'h'), ('x3', 'c'), ('next', 'P')])
+        x = X(x2=3)
+        a = A(3)
+        a[1] = x
+        get_array_elem_s = lib.ptr('get_array_elem_s', ['P', 'i'], 'P')
+        ptr1 = get_array_elem_s(a, 0)
+        assert ptr1 is None
+        assert X(get_array_elem_s(a, 1)).x2 == 3
+
     def test_implicit_structure(self):
         skip("Does not work yet")
         import _ffi



More information about the Pypy-commit mailing list