Author: Amaury Forgeot d'Arc <amaur...@gmail.com> Branch: Changeset: r47642:59a89b3bca04 Date: 2011-09-20 21:46 +0200 http://bitbucket.org/pypy/pypy/changeset/59a89b3bca04/
Log: Fix a recursion issue in ll2ctypes, when a struct contains a substructure and a pointer to this substructure. diff --git a/pypy/rpython/lltypesystem/ll2ctypes.py b/pypy/rpython/lltypesystem/ll2ctypes.py --- a/pypy/rpython/lltypesystem/ll2ctypes.py +++ b/pypy/rpython/lltypesystem/ll2ctypes.py @@ -140,7 +140,8 @@ if isinstance(FIELDTYPE, lltype.Ptr): cls = get_ctypes_type(FIELDTYPE, delayed_builders) else: - cls = get_ctypes_type(FIELDTYPE) + cls = get_ctypes_type(FIELDTYPE, delayed_builders, + cannot_delay=True) fields.append((fieldname, cls)) CStruct._fields_ = fields @@ -169,7 +170,7 @@ CStruct._normalized_ctype = get_ctypes_type(S) builder() # no need to be lazy here else: - delayed_builders.append(builder) + delayed_builders.append((S, builder)) return CStruct def build_ctypes_array(A, delayed_builders, max_n=0): @@ -252,11 +253,19 @@ else: return get_ctypes_type(FIELDTYPE) -def get_ctypes_type(T, delayed_builders=None): +def get_ctypes_type(T, delayed_builders=None, cannot_delay=False): + # Check delayed builders + if cannot_delay and delayed_builders: + for T2, builder in delayed_builders: + if T2 is T: + builder() + delayed_builders.remove((T2, builder)) + return _ctypes_cache[T] + try: return _ctypes_cache[T] except KeyError: - toplevel = delayed_builders is None + toplevel = cannot_delay or delayed_builders is None if toplevel: delayed_builders = [] cls = build_new_ctypes_type(T, delayed_builders) @@ -306,9 +315,11 @@ def complete_builders(delayed_builders): while delayed_builders: - delayed_builders.pop()() + T, builder = delayed_builders[0] + builder() + delayed_builders.pop(0) -def convert_struct(container, cstruct=None): +def convert_struct(container, cstruct=None, delayed_converters=None): STRUCT = container._TYPE if cstruct is None: # if 'container' is an inlined substructure, convert the whole @@ -325,23 +336,38 @@ n = None cstruct = cls._malloc(n) add_storage(container, _struct_mixin, ctypes.pointer(cstruct)) + + if delayed_converters is None: + delayed_converters_was_None = True + delayed_converters = [] + else: + delayed_converters_was_None = False for field_name in STRUCT._names: FIELDTYPE = getattr(STRUCT, field_name) field_value = getattr(container, field_name) if not isinstance(FIELDTYPE, lltype.ContainerType): # regular field if FIELDTYPE != lltype.Void: - setattr(cstruct, field_name, lltype2ctypes(field_value)) + def convert(field_name=field_name, field_value=field_value): + setattr(cstruct, field_name, lltype2ctypes(field_value)) + if isinstance(FIELDTYPE, lltype.Ptr): + delayed_converters.append(convert) + else: + convert() else: # inlined substructure/subarray if isinstance(FIELDTYPE, lltype.Struct): csubstruct = getattr(cstruct, field_name) - convert_struct(field_value, csubstruct) + convert_struct(field_value, csubstruct, + delayed_converters=delayed_converters) elif field_name == STRUCT._arrayfld: # inlined var-sized part csubarray = getattr(cstruct, field_name) convert_array(field_value, csubarray) else: raise NotImplementedError('inlined field', FIELDTYPE) + if delayed_converters_was_None: + for converter in delayed_converters: + converter() remove_regular_struct_content(container) def remove_regular_struct_content(container): @@ -358,7 +384,8 @@ # bigger structure at once parent, parentindex = lltype.parentlink(container) if parent is not None: - convert_struct(parent) + if not isinstance(parent, _parentable_mixin): + convert_struct(parent) return # regular case: allocate a new ctypes array of the proper type cls = get_ctypes_type(ARRAY) diff --git a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py --- a/pypy/rpython/lltypesystem/test/test_ll2ctypes.py +++ b/pypy/rpython/lltypesystem/test/test_ll2ctypes.py @@ -82,7 +82,6 @@ assert not ALLOCATED # detects memory leaks in the test def test_get_pointer(self): - py.test.skip("FIXME") # Equivalent of the C code:: # struct S1 { struct S2 *ptr; struct S2 buf; }; # struct S1 s1; _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit