Author: Armin Rigo <ar...@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) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit