diff --git a/src/c/_cffi_backend.c b/src/c/_cffi_backend.c index d53a06c0..e5ff9d5b 100644 --- a/src/c/_cffi_backend.c +++ b/src/c/_cffi_backend.c @@ -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)) { @@ -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 diff --git a/src/c/cdlopen.c b/src/c/cdlopen.c index 0ed319b8..7db7ae28 100644 --- a/src/c/cdlopen.c +++ b/src/c/cdlopen.c @@ -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]; diff --git a/testing/cffi1/test_re_python.py b/testing/cffi1/test_re_python.py index 5311893e..91edd9b7 100644 --- a/testing/cffi1/test_re_python.py +++ b/testing/cffi1/test_re_python.py @@ -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 *")