Skip to content

Commit b57a92c

Browse files
authored
issue 147: force-compute nested structs before parent structs. Occurs mainly in out-of-line ABI mode. (#148)
1 parent f44941e commit b57a92c

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

src/c/_cffi_backend.c

+7-3
Original file line numberDiff line numberDiff line change
@@ -5238,6 +5238,13 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args)
52385238
&fbitsize, &foffset))
52395239
goto error;
52405240

5241+
if ((ftype->ct_flags & (CT_STRUCT | CT_UNION)) &&
5242+
!(ftype->ct_flags & CT_IS_OPAQUE)) {
5243+
/* force now the type of the nested field */
5244+
if (force_lazy_struct(ftype) < 0)
5245+
return NULL;
5246+
}
5247+
52415248
if (ftype->ct_size < 0) {
52425249
if ((ftype->ct_flags & CT_ARRAY) && fbitsize < 0
52435250
&& (i == nb_fields - 1 || foffset != -1)) {
@@ -5252,9 +5259,6 @@ static PyObject *b_complete_struct_or_union(PyObject *self, PyObject *args)
52525259
}
52535260
}
52545261
else if (ftype->ct_flags & (CT_STRUCT|CT_UNION)) {
5255-
if (force_lazy_struct(ftype) < 0) /* for CT_WITH_VAR_ARRAY */
5256-
return NULL;
5257-
52585262
/* GCC (or maybe C99) accepts var-sized struct fields that are not
52595263
the last field of a larger struct. That's why there is no
52605264
check here for "last field": we propagate the flag

src/c/cdlopen.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ static PyObject *ffi_dlclose(PyObject *self, PyObject *args)
8181

8282
static Py_ssize_t cdl_4bytes(char *src)
8383
{
84-
/* read 4 bytes in little-endian order; return it as a signed integer */
84+
/* read 4 bytes in big-endian order; return it as a signed integer */
8585
signed char *ssrc = (signed char *)src;
8686
unsigned char *usrc = (unsigned char *)src;
8787
return (ssrc[0] << 24) | (usrc[1] << 16) | (usrc[2] << 8) | usrc[3];

testing/cffi1/test_re_python.py

+30
Original file line numberDiff line numberDiff line change
@@ -286,3 +286,33 @@ def test_dlopen_handle():
286286

287287
err = lib1.dlclose(handle)
288288
assert err == 0
289+
290+
def test_rec_structs_1():
291+
ffi = FFI()
292+
ffi.cdef("struct B { struct C* c; }; struct C { struct B b; };")
293+
ffi.set_source('test_rec_structs_1', None)
294+
ffi.emit_python_code(str(tmpdir.join('_rec_structs_1.py')))
295+
#
296+
if sys.version_info[:2] >= (3, 3):
297+
import importlib
298+
importlib.invalidate_caches() # issue 197, maybe
299+
#
300+
from _rec_structs_1 import ffi
301+
# the following line used to raise TypeError
302+
# unless preceeded by 'ffi.sizeof("struct C")'.
303+
sz = ffi.sizeof("struct B")
304+
assert sz == ffi.sizeof("int *")
305+
306+
def test_rec_structs_2():
307+
ffi = FFI()
308+
ffi.cdef("struct B { struct C* c; }; struct C { struct B b; };")
309+
ffi.set_source('test_rec_structs_2', None)
310+
ffi.emit_python_code(str(tmpdir.join('_rec_structs_2.py')))
311+
#
312+
if sys.version_info[:2] >= (3, 3):
313+
import importlib
314+
importlib.invalidate_caches() # issue 197, maybe
315+
#
316+
from _rec_structs_2 import ffi
317+
sz = ffi.sizeof("struct C")
318+
assert sz == ffi.sizeof("int *")

0 commit comments

Comments
 (0)