Author: Antonio Cuni <[email protected]>
Branch: ffistruct
Changeset: r55099:58e8161a5deb
Date: 2012-05-15 11:25 +0200
http://bitbucket.org/pypy/pypy/changeset/58e8161a5deb/

Log:    kill support for _rawffi structures and add support for _ffi
        structures. Some tests fail because we leak
        W__StructDescr.ffistruct, in-progress

diff --git a/pypy/module/_ffi/interp_ffitype.py 
b/pypy/module/_ffi/interp_ffitype.py
--- a/pypy/module/_ffi/interp_ffitype.py
+++ b/pypy/module/_ffi/interp_ffitype.py
@@ -1,4 +1,4 @@
-from pypy.rlib import libffi
+from pypy.rlib import libffi, clibffi
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib import jit
 from pypy.interpreter.baseobjspace import Wrappable
@@ -12,12 +12,10 @@
 
     def __init__(self, name, ffitype, w_datashape=None, w_pointer_to=None):
         self.name = name
-        self._ffitype = ffitype
+        self._ffitype = clibffi.FFI_TYPE_NULL
         self.w_datashape = w_datashape
         self.w_pointer_to = w_pointer_to
-        ## XXX: re-enable this check when the ffistruct branch is done
-        ## if self.is_struct():
-        ##     assert w_datashape is not None
+        self.set_ffitype(ffitype)
 
     @jit.elidable
     def get_ffitype(self):
@@ -29,6 +27,8 @@
         if self._ffitype:
             raise ValueError("The _ffitype is already set")
         self._ffitype = ffitype
+        if ffitype and self.is_struct():
+            assert self.w_datashape is not None
 
     def descr_deref_pointer(self, space):
         if self.w_pointer_to is None:
diff --git a/pypy/module/_ffi/interp_funcptr.py 
b/pypy/module/_ffi/interp_funcptr.py
--- a/pypy/module/_ffi/interp_funcptr.py
+++ b/pypy/module/_ffi/interp_funcptr.py
@@ -125,7 +125,7 @@
         self.argchain.arg(singlefloatval)
 
     def handle_struct(self, w_ffitype, w_structinstance):
-        ptrval = w_structinstance.ll_buffer
+        ptrval = w_structinstance.rawmem
         self.argchain.arg_raw(ptrval)
 
 
@@ -204,7 +204,7 @@
         return self.func.call(self.argchain, rffi.FLOAT)
 
     def get_struct(self, w_datashape):
-        return self.func.call(self.argchain, rffi.ULONG, is_struct=True)
+        return self.func.call(self.argchain, rffi.LONG, is_struct=True)
 
     def get_void(self, w_ffitype):
         return self.func.call(self.argchain, lltype.Void)
diff --git a/pypy/module/_ffi/interp_struct.py 
b/pypy/module/_ffi/interp_struct.py
--- a/pypy/module/_ffi/interp_struct.py
+++ b/pypy/module/_ffi/interp_struct.py
@@ -43,7 +43,8 @@
 
     def __init__(self, space, name):
         self.space = space
-        self.w_ffitype = W_FFIType('struct %s' % name, clibffi.FFI_TYPE_NULL, 
None)
+        self.w_ffitype = W_FFIType('struct %s' % name, clibffi.FFI_TYPE_NULL,
+                                   w_datashape=self)
         self.fields_w = None
         self.name2w_field = {}
 
@@ -65,12 +66,21 @@
         self.ffistruct = clibffi.make_struct_ffitype_e(size, alignment, 
field_types)
         self.w_ffitype.set_ffitype(self.ffistruct.ffistruct)
 
-    def allocate(self, space):
+    def check_complete(self):
         if self.fields_w is None:
             raise operationerrfmt(space.w_ValueError, "%s has an incomplete 
type",
                                   self.w_ffitype.name)
+
+    def allocate(self, space):
+        self.check_complete()
         return W__StructInstance(self)
 
+    @unwrap_spec(addr=int)
+    def fromaddress(self, space, addr):
+        self.check_complete()
+        rawmem = rffi.cast(rffi.VOIDP, addr)
+        return W__StructInstance(self, allocate=False, autofree=True, 
rawmem=rawmem)
+
     @jit.elidable_promote('0')
     def get_type_and_offset_for_field(self, name):
         try:
@@ -121,24 +131,33 @@
     ffitype = interp_attrproperty('w_ffitype', W__StructDescr),
     define_fields = interp2app(W__StructDescr.define_fields),
     allocate = interp2app(W__StructDescr.allocate),
+    fromaddress = interp2app(W__StructDescr.fromaddress),
     )
 
 
 # 
==============================================================================
 
+NULL = lltype.nullptr(rffi.VOIDP.TO)
+
 class W__StructInstance(Wrappable):
 
     _immutable_fields_ = ['structdescr', 'rawmem']
 
-    def __init__(self, structdescr):
+    def __init__(self, structdescr, allocate=True, autofree=True, rawmem=NULL):
         self.structdescr = structdescr
-        size = structdescr.w_ffitype.sizeof()
-        self.rawmem = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw',
-                                    zero=True, add_memory_pressure=True)
+        self.autofree = autofree
+        if allocate:
+            assert not rawmem
+            assert autofree
+            size = structdescr.w_ffitype.sizeof()
+            self.rawmem = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw',
+                                        zero=True, add_memory_pressure=True)
+        else:
+            self.rawmem = rawmem
 
     @must_be_light_finalizer
     def __del__(self):
-        if self.rawmem:
+        if self.autofree and self.rawmem:
             lltype.free(self.rawmem, flavor='raw')
             self.rawmem = lltype.nullptr(rffi.VOIDP.TO)
 
diff --git a/pypy/module/_ffi/test/test_funcptr.py 
b/pypy/module/_ffi/test/test_funcptr.py
--- a/pypy/module/_ffi/test/test_funcptr.py
+++ b/pypy/module/_ffi/test/test_funcptr.py
@@ -452,19 +452,19 @@
                 return p.x + p.y;
             }
         """
-        import _rawffi
-        from _ffi import CDLL, types
-        POINT = _rawffi.Structure([('x', 'l'), ('y', 'l')])
-        ffi_point = POINT.get_ffi_type()
+        from _ffi import CDLL, types, _StructDescr, Field
+        Point = _StructDescr('Point', [
+                Field('x', types.slong),
+                Field('y', types.slong),
+                ])
         libfoo = CDLL(self.libfoo_name)
-        sum_point = libfoo.getfunc('sum_point', [ffi_point], types.slong)
+        sum_point = libfoo.getfunc('sum_point', [Point.ffitype], types.slong)
         #
-        p = POINT()
-        p.x = 30
-        p.y = 12
+        p = Point.allocate()
+        p.setfield('x', 30)
+        p.setfield('y', 12)
         res = sum_point(p)
         assert res == 42
-        p.free()
 
     def test_byval_result(self):
         """
@@ -475,17 +475,18 @@
                 return p;
             }
         """
-        import _rawffi
-        from _ffi import CDLL, types
-        POINT = _rawffi.Structure([('x', 'l'), ('y', 'l')])
-        ffi_point = POINT.get_ffi_type()
+        from _ffi import CDLL, types, _StructDescr, Field
+        Point = _StructDescr('Point', [
+                Field('x', types.slong),
+                Field('y', types.slong),
+                ])
         libfoo = CDLL(self.libfoo_name)
-        make_point = libfoo.getfunc('make_point', [types.slong, types.slong], 
ffi_point)
+        make_point = libfoo.getfunc('make_point', [types.slong, types.slong],
+                                    Point.ffitype)
         #
         p = make_point(12, 34)
-        assert p.x == 12
-        assert p.y == 34
-        p.free()
+        assert p.getfield('x') == 12
+        assert p.getfield('y') == 34
 
     def test_TypeError_numargs(self):
         from _ffi import CDLL, types
diff --git a/pypy/module/_ffi/type_converter.py 
b/pypy/module/_ffi/type_converter.py
--- a/pypy/module/_ffi/type_converter.py
+++ b/pypy/module/_ffi/type_converter.py
@@ -3,7 +3,6 @@
 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):
@@ -18,6 +17,7 @@
         self.space = space
 
     def unwrap_and_do(self, w_ffitype, w_obj):
+        from pypy.module._ffi.interp_struct import W__StructInstance
         space = self.space
         if w_ffitype.is_longlong():
             # note that we must check for longlong first, because either
@@ -50,7 +50,7 @@
             self._singlefloat(w_ffitype, w_obj)
         elif w_ffitype.is_struct():
             # arg_raw directly takes value to put inside ll_args
-            w_obj = space.interp_w(W_StructureInstance, w_obj)
+            w_obj = space.interp_w(W__StructInstance, w_obj)
             self.handle_struct(w_ffitype, w_obj)
         else:
             self.error(w_ffitype, w_obj)
@@ -183,6 +183,7 @@
         self.space = space
 
     def do_and_wrap(self, w_ffitype):
+        from pypy.module._ffi.interp_struct import W__StructDescr
         space = self.space
         if w_ffitype.is_longlong():
             # note that we must check for longlong first, because either
@@ -222,9 +223,9 @@
             return self._singlefloat(w_ffitype)
         elif w_ffitype.is_struct():
             w_datashape = w_ffitype.w_datashape
-            assert isinstance(w_datashape, W_Structure)
-            uintval = self.get_struct(w_datashape) # this is the ptr to the 
struct
-            return w_datashape.fromaddress(space, uintval)
+            assert isinstance(w_datashape, W__StructDescr)
+            addr = self.get_struct(w_datashape) # this is the ptr to the struct
+            return w_datashape.fromaddress(space, addr)
         elif w_ffitype.is_void():
             voidval = self.get_void(w_ffitype)
             assert voidval is None
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to