[pypy-commit] pypy cffi-1.0: ffi.addressof()

arigo noreply at buildbot.pypy.org
Sun May 3 11:16:42 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r76999:5ca8a8504353
Date: 2015-05-03 11:03 +0200
http://bitbucket.org/pypy/pypy/changeset/5ca8a8504353/

Log:	ffi.addressof()

diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -142,6 +142,24 @@
         raise oefmt(space.w_ValueError, "ctype '%s' is of unknown alignment",
                     self.name)
 
+    def direct_typeoffsetof(self, w_field_or_index, following=0):
+        space = self.space
+        try:
+            fieldname = space.str_w(w_field_or_index)
+        except OperationError, e:
+            if not e.match(space, space.w_TypeError):
+                raise
+            try:
+                index = space.int_w(w_field_or_index)
+            except OperationError, e:
+                if not e.match(space, space.w_TypeError):
+                    raise
+                raise OperationError(space.w_TypeError,
+                        space.wrap("field name or array index expected"))
+            return self.typeoffsetof_index(index)
+        else:
+            return self.typeoffsetof_field(fieldname, following)
+
     def typeoffsetof_field(self, fieldname, following):
         space = self.space
         msg = "with a field name argument, expected a struct or union ctype"
diff --git a/pypy/module/_cffi_backend/ffi_obj.py b/pypy/module/_cffi_backend/ffi_obj.py
--- a/pypy/module/_cffi_backend/ffi_obj.py
+++ b/pypy/module/_cffi_backend/ffi_obj.py
@@ -3,9 +3,11 @@
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
 from rpython.rlib import jit, rgc
+from rpython.rtyper.lltypesystem import rffi
 
 from pypy.module._cffi_backend import parse_c_type, realize_c_type
 from pypy.module._cffi_backend import newtype, cerrno, ccallback, ctypearray
+from pypy.module._cffi_backend import ctypestruct, ctypeptr
 from pypy.module._cffi_backend.ctypeobj import W_CType
 from pypy.module._cffi_backend.cdataobj import W_CData
 
@@ -85,6 +87,38 @@
         cerrno.set_errno(space, space.c_int_w(errno))
 
 
+    def descr_addressof(self, w_arg, args_w):
+        """\
+With a single arg, return the address of a <cdata 'struct-or-union'>.
+If 'fields_or_indexes' are given, returns the address of that field or
+array item in the structure or array, recursively in case of nested
+structures."""
+        #
+        w_ctype = self.ffi_type(w_arg, ACCEPT_CDATA)
+        space = self.space
+        offset = 0
+        if len(args_w) == 0:
+            if (not isinstance(w_ctype, ctypestruct.W_CTypeStructOrUnion) and
+                not isinstance(w_ctype, ctypearray.W_CTypeArray)):
+                raise oefmt(space.w_TypeError,
+                            "expected a cdata struct/union/array object")
+        else:
+            if (not isinstance(w_ctype, ctypestruct.W_CTypeStructOrUnion) and
+                not isinstance(w_ctype, ctypearray.W_CTypeArray) and
+                not isinstance(w_ctype, ctypeptr.W_CTypePointer)):
+                raise oefmt(space.w_TypeError,
+                        "expected a cdata struct/union/array/pointer object")
+            for i in range(len(args_w)):
+                w_ctype, ofs1 = w_ctype.direct_typeoffsetof(args_w[i], i > 0)
+                offset += ofs1
+        #
+        assert isinstance(w_arg, W_CData)
+        cdata = w_arg.unsafe_escaping_ptr()
+        cdata = rffi.ptradd(cdata, offset)
+        w_ctypeptr = newtype.new_pointer_type(space, w_ctype)
+        return W_CData(space, cdata, w_ctypeptr)
+
+
     def descr_alignof(self, w_arg):
         """\
 Return the natural alignment size in bytes of the argument.
@@ -236,6 +270,7 @@
                                      W_FFIObject.set_errno,
                                      doc=W_FFIObject.doc_errno,
                                      cls=W_FFIObject),
+        addressof   = interp2app(W_FFIObject.descr_addressof),
         alignof     = interp2app(W_FFIObject.descr_alignof),
         callback    = interp2app(W_FFIObject.descr_callback),
         getctype    = interp2app(W_FFIObject.descr_getctype),
diff --git a/pypy/module/_cffi_backend/func.py b/pypy/module/_cffi_backend/func.py
--- a/pypy/module/_cffi_backend/func.py
+++ b/pypy/module/_cffi_backend/func.py
@@ -50,22 +50,7 @@
 
 @unwrap_spec(w_ctype=ctypeobj.W_CType, following=int)
 def typeoffsetof(space, w_ctype, w_field_or_index, following=0):
-    try:
-        fieldname = space.str_w(w_field_or_index)
-    except OperationError, e:
-        if not e.match(space, space.w_TypeError):
-            raise
-        try:
-            index = space.int_w(w_field_or_index)
-        except OperationError, e:
-            if not e.match(space, space.w_TypeError):
-                raise
-            raise OperationError(space.w_TypeError,
-                    space.wrap("field name or array index expected"))
-        ctype, offset = w_ctype.typeoffsetof_index(index)
-    else:
-        ctype, offset = w_ctype.typeoffsetof_field(fieldname, following)
-    #
+    ctype, offset = w_ctype.direct_typeoffsetof(w_field_or_index, following)
     return space.newtuple([space.wrap(ctype), space.wrap(offset)])
 
 @unwrap_spec(w_ctype=ctypeobj.W_CType, w_cdata=cdataobj.W_CData, offset=int)


More information about the pypy-commit mailing list