[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