Author: Armin Rigo <[email protected]>
Branch:
Changeset: r1611:bcdbd8bc0c38
Date: 2014-12-30 03:58 +0100
http://bitbucket.org/cffi/cffi/changeset/bcdbd8bc0c38/
Log: issue #169: offsetof('struct', 'a.b.c')
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -192,11 +192,12 @@
def offsetof(self, cdecl, fieldname):
"""Return the offset of the named field inside the given
- structure, which must be given as a C type name.
+ structure, which must be given as a C type name. The field
+ may be 'x.y.z' in case of nested structures.
"""
if isinstance(cdecl, basestring):
cdecl = self._typeof(cdecl)
- return self._backend.typeoffsetof(cdecl, fieldname)[1]
+ return self._typeoffsetof(cdecl, fieldname)[1]
def new(self, cdecl, init=None):
"""Allocate an instance according to the specified C type and
@@ -369,12 +370,22 @@
def addressof(self, cdata, field=None):
"""Return the address of a <cdata 'struct-or-union'>.
If 'field' is specified, return the address of this field.
+ The field may be 'x.y.z' in case of nested structures.
"""
ctype = self._backend.typeof(cdata)
- ctype, offset = self._backend.typeoffsetof(ctype, field)
+ ctype, offset = self._typeoffsetof(ctype, field)
ctypeptr = self._pointer_to(ctype)
return self._backend.rawaddressof(ctypeptr, cdata, offset)
+ def _typeoffsetof(self, ctype, field):
+ if field is not None and '.' in field:
+ offset = 0
+ for field1 in field.split('.'):
+ ctype, offset1 = self._backend.typeoffsetof(ctype, field1)
+ offset += offset1
+ return ctype, offset
+ return self._backend.typeoffsetof(ctype, field)
+
def include(self, ffi_to_include):
"""Includes the typedefs, structs, unions and enums defined
in another FFI instance. Usage is similar to a #include in C,
diff --git a/testing/backend_tests.py b/testing/backend_tests.py
--- a/testing/backend_tests.py
+++ b/testing/backend_tests.py
@@ -949,6 +949,15 @@
assert ffi.offsetof("struct foo", "b") == 4
assert ffi.offsetof("struct foo", "c") == 8
+ def test_offsetof_nested(self):
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("struct foo { int a, b, c; };"
+ "struct bar { struct foo d, e; };")
+ assert ffi.offsetof("struct bar", "e") == 12
+ assert ffi.offsetof("struct bar", "e.a") == 12
+ assert ffi.offsetof("struct bar", "e.b") == 16
+ assert ffi.offsetof("struct bar", "e.c") == 20
+
def test_alignof(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct foo { char a; short b; char c; };")
@@ -1495,6 +1504,16 @@
assert a == ffi.addressof(p, 'y')
assert a != ffi.addressof(p, 'x')
+ def test_addressof_field_nested(self):
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("struct foo_s { int x, y; };"
+ "struct bar_s { struct foo_s a, b; };")
+ p = ffi.new("struct bar_s *")
+ a = ffi.addressof(p[0], 'b.y')
+ assert int(ffi.cast("uintptr_t", a)) == (
+ int(ffi.cast("uintptr_t", p)) +
+ ffi.sizeof("struct foo_s") + ffi.sizeof("int"))
+
def test_addressof_anonymous_struct(self):
ffi = FFI()
ffi.cdef("typedef struct { int x; } foo_t;")
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit