Skip to content

Commit

Permalink
issue 147: force-compute nested structs before parent structs. Occurs…
Browse files Browse the repository at this point in the history
… mainly in out-of-line ABI mode. (#148)
  • Loading branch information
arigo authored Dec 9, 2024
1 parent f44941e commit b57a92c
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 4 deletions.
10 changes: 7 additions & 3 deletions src/c/_cffi_backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -5238,6 +5238,13 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args)
&fbitsize, &foffset))
goto error;

if ((ftype->ct_flags & (CT_STRUCT | CT_UNION)) &&
!(ftype->ct_flags & CT_IS_OPAQUE)) {
/* force now the type of the nested field */
if (force_lazy_struct(ftype) < 0)
return NULL;
}

if (ftype->ct_size < 0) {
if ((ftype->ct_flags & CT_ARRAY) && fbitsize < 0
&& (i == nb_fields - 1 || foffset != -1)) {
Expand All @@ -5252,9 +5259,6 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args)
}
}
else if (ftype->ct_flags & (CT_STRUCT|CT_UNION)) {
if (force_lazy_struct(ftype) < 0) /* for CT_WITH_VAR_ARRAY */
return NULL;

/* GCC (or maybe C99) accepts var-sized struct fields that are not
the last field of a larger struct. That's why there is no
check here for "last field": we propagate the flag
Expand Down
2 changes: 1 addition & 1 deletion src/c/cdlopen.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ static PyObject *ffi_dlclose(PyObject *self, PyObject *args)

static Py_ssize_t cdl_4bytes(char *src)
{
/* read 4 bytes in little-endian order; return it as a signed integer */
/* read 4 bytes in big-endian order; return it as a signed integer */
signed char *ssrc = (signed char *)src;
unsigned char *usrc = (unsigned char *)src;
return (ssrc[0] << 24) | (usrc[1] << 16) | (usrc[2] << 8) | usrc[3];
Expand Down
30 changes: 30 additions & 0 deletions testing/cffi1/test_re_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,3 +286,33 @@ def test_dlopen_handle():

err = lib1.dlclose(handle)
assert err == 0

def test_rec_structs_1():
ffi = FFI()
ffi.cdef("struct B { struct C* c; }; struct C { struct B b; };")
ffi.set_source('test_rec_structs_1', None)
ffi.emit_python_code(str(tmpdir.join('_rec_structs_1.py')))
#
if sys.version_info[:2] >= (3, 3):
import importlib
importlib.invalidate_caches() # issue 197, maybe
#
from _rec_structs_1 import ffi
# the following line used to raise TypeError
# unless preceeded by 'ffi.sizeof("struct C")'.
sz = ffi.sizeof("struct B")
assert sz == ffi.sizeof("int *")

def test_rec_structs_2():
ffi = FFI()
ffi.cdef("struct B { struct C* c; }; struct C { struct B b; };")
ffi.set_source('test_rec_structs_2', None)
ffi.emit_python_code(str(tmpdir.join('_rec_structs_2.py')))
#
if sys.version_info[:2] >= (3, 3):
import importlib
importlib.invalidate_caches() # issue 197, maybe
#
from _rec_structs_2 import ffi
sz = ffi.sizeof("struct C")
assert sz == ffi.sizeof("int *")

0 comments on commit b57a92c

Please sign in to comment.