Commits

Antonio Cuni  committed 15f1a0a Draft

temporarly re-add support for _rawffi structures. This way, it should be possible to merge the branch without breaking ctypes. In the longterm, the plan is to implement ctypes.Structure on top of _ffi._StructDescr

  • Participants
  • Parent commits 1789dd2
  • Branches ffistruct

Comments (0)

Files changed (3)

File pypy/module/_ffi/interp_funcptr.py

         ptrval = w_structinstance.rawmem
         self.argchain.arg_raw(ptrval)
 
+    def handle_struct_rawffi(self, w_ffitype, w_structinstance):
+        # arg_raw directly takes value to put inside ll_args
+        ptrval = w_structinstance.ll_buffer
+        self.argchain.arg_raw(ptrval)
+
 
 class CallFunctionConverter(ToAppLevelConverter):
     """
         addr = self.func.call(self.argchain, rffi.LONG, is_struct=True)
         return w_structdescr.fromaddress(self.space, addr)
 
+    def get_struct_rawffi(self, w_ffitype, w_structdescr):
+        uintval = self.func.call(self.argchain, rffi.ULONG, is_struct=True)
+        return w_structdescr.fromaddress(self.space, uintval)
+
     def get_void(self, w_ffitype):
         return self.func.call(self.argchain, lltype.Void)
     

File pypy/module/_ffi/test/test_funcptr.py

         assert p.getfield('x') == 12
         assert p.getfield('y') == 34
 
+    # XXX: support for _rawffi structures should be killed as soon as we
+    # implement ctypes.Structure on top of _ffi. In the meantime, we support
+    # both
+    def test_byval_argument__rawffi(self):
+        """
+            // defined above
+            struct Point;
+            DLLEXPORT long sum_point(struct Point p);
+        """
+        import _rawffi
+        from _ffi import CDLL, types
+        POINT = _rawffi.Structure([('x', 'l'), ('y', 'l')])
+        ffi_point = POINT.get_ffi_type()
+        libfoo = CDLL(self.libfoo_name)
+        sum_point = libfoo.getfunc('sum_point', [ffi_point], types.slong)
+        #
+        p = POINT()
+        p.x = 30
+        p.y = 12
+        res = sum_point(p)
+        assert res == 42
+        p.free()
+
+    def test_byval_result__rawffi(self):
+        """
+            // defined above
+            DLLEXPORT struct Point make_point(long x, long y);
+        """
+        import _rawffi
+        from _ffi import CDLL, types
+        POINT = _rawffi.Structure([('x', 'l'), ('y', 'l')])
+        ffi_point = POINT.get_ffi_type()
+        libfoo = CDLL(self.libfoo_name)
+        make_point = libfoo.getfunc('make_point', [types.slong, types.slong], ffi_point)
+        #
+        p = make_point(12, 34)
+        assert p.x == 12
+        assert p.y == 34
+        p.free()
+
+
     def test_TypeError_numargs(self):
         from _ffi import CDLL, types
         libfoo = CDLL(self.libfoo_name)

File pypy/module/_ffi/type_converter.py

 from pypy.rlib.rarithmetic import intmask, r_uint
 from pypy.rpython.lltypesystem import rffi
 from pypy.interpreter.error import operationerrfmt
+from pypy.module._rawffi.structure import W_StructureInstance, W_Structure
 from pypy.module._ffi.interp_ffitype import app_types
 
 class FromAppLevelConverter(object):
         elif w_ffitype.is_singlefloat():
             self._singlefloat(w_ffitype, w_obj)
         elif w_ffitype.is_struct():
-            w_obj = space.interp_w(W__StructInstance, w_obj)
-            self.handle_struct(w_ffitype, w_obj)
+            if isinstance(w_obj, W_StructureInstance):
+                self.handle_struct_rawffi(w_ffitype, w_obj)
+            else:
+                w_obj = space.interp_w(W__StructInstance, w_obj)
+                self.handle_struct(w_ffitype, w_obj)
         else:
             self.error(w_ffitype, w_obj)
 
         """
         self.error(w_ffitype, w_structinstance)
 
+    def handle_struct_rawffi(self, w_ffitype, w_structinstance):
+        """
+        This method should be killed as soon as we remove support for _rawffi structures
+        
+        w_structinstance: W_StructureInstance
+        """
+        self.error(w_ffitype, w_structinstance)
+
 
 
 class ToAppLevelConverter(object):
             return self._singlefloat(w_ffitype)
         elif w_ffitype.is_struct():
             w_structdescr = w_ffitype.w_structdescr
-            assert isinstance(w_structdescr, W__StructDescr)
-            return self.get_struct(w_ffitype, w_structdescr)
+            if isinstance(w_structdescr, W__StructDescr):
+                return self.get_struct(w_ffitype, w_structdescr)
+            elif isinstance(w_structdescr, W_Structure):
+                return self.get_struct_rawffi(w_ffitype, w_structdescr)
+            else:
+                raise OperationError(self.space.w_TypeError, "Unsupported struct shape")
         elif w_ffitype.is_void():
             voidval = self.get_void(w_ffitype)
             assert voidval is None
 
     def get_struct(self, w_ffitype, w_structdescr):
         """
+        Return type: lltype.Signed
+        (the address of the structure)
+        """
+        self.error(w_ffitype)
+
+    def get_struct_rawffi(self, w_ffitype, w_structdescr):
+        """
+        This should be killed as soon as we kill support for _rawffi structures
+        
         Return type: lltype.Unsigned
         (the address of the structure)
         """