Author: Armin Rigo <ar...@tunes.org>
Branch: cffi-1.0
Changeset: r77223:f259e960f2a7
Date: 2015-05-08 17:51 +0200
http://bitbucket.org/pypy/pypy/changeset/f259e960f2a7/

Log:    Next test

diff --git a/pypy/module/_cffi_backend/ffi_obj.py 
b/pypy/module/_cffi_backend/ffi_obj.py
--- a/pypy/module/_cffi_backend/ffi_obj.py
+++ b/pypy/module/_cffi_backend/ffi_obj.py
@@ -44,6 +44,7 @@
         else:
             self.cached_types = None
         self.w_FFIError = get_ffi_error(space)
+        self.included_libs = []        # list of W_LibObject's included here
 
     @jit.elidable
     def parse_string_to_type(self, string, flags):
diff --git a/pypy/module/_cffi_backend/lib_obj.py 
b/pypy/module/_cffi_backend/lib_obj.py
--- a/pypy/module/_cffi_backend/lib_obj.py
+++ b/pypy/module/_cffi_backend/lib_obj.py
@@ -20,7 +20,6 @@
         self.ffi = ffi
         self.dict_w = {}          # content, built lazily
         self.libname = libname    # some string that gives the name of the lib
-        self.includes = []        # list of W_LibObjects included here
 
     def descr_repr(self):
         return self.space.wrap("<Lib object for '%s'>" % self.libname)
@@ -37,7 +36,7 @@
             lib1 = space.interp_w(W_LibObject, w_lib1)
             includes.append(lib1)
             num += 1
-        self.includes = includes[:]
+        self.ffi.included_libs = includes[:]
 
     @jit.elidable_promote()
     def _get_attr_elidable(self, attr):
@@ -46,7 +45,7 @@
         except KeyError:
             index = parse_c_type.search_in_globals(self.ctx, attr)
             if index < 0:
-                for lib1 in self.includes:
+                for lib1 in self.ffi.included_libs:
                     w_result = lib1._get_attr_elidable(attr)
                     if w_result is not None:
                         return w_result
diff --git a/pypy/module/_cffi_backend/parse_c_type.py 
b/pypy/module/_cffi_backend/parse_c_type.py
--- a/pypy/module/_cffi_backend/parse_c_type.py
+++ b/pypy/module/_cffi_backend/parse_c_type.py
@@ -73,6 +73,9 @@
 ll_search_in_globals = llexternal('pypy_search_in_globals',
                                   [PCTX, rffi.CCHARP, rffi.SIZE_T],
                                   rffi.INT)
+ll_search_in_struct_unions = llexternal('pypy_search_in_struct_unions',
+                                        [PCTX, rffi.CCHARP, rffi.SIZE_T],
+                                        rffi.INT)
 
 def parse_c_type(info, input):
     p_input = rffi.str2charp(input)
@@ -113,3 +116,10 @@
                                   rffi.cast(rffi.SIZE_T, len(name)))
     rffi.free_charp(c_name)
     return rffi.cast(lltype.Signed, result)
+
+def search_in_struct_unions(ctx, name):
+    c_name = rffi.str2charp(name)
+    result = ll_search_in_struct_unions(ctx, c_name,
+                                        rffi.cast(rffi.SIZE_T, len(name)))
+    rffi.free_charp(c_name)
+    return rffi.cast(lltype.Signed, result)
diff --git a/pypy/module/_cffi_backend/realize_c_type.py 
b/pypy/module/_cffi_backend/realize_c_type.py
--- a/pypy/module/_cffi_backend/realize_c_type.py
+++ b/pypy/module/_cffi_backend/realize_c_type.py
@@ -183,7 +183,12 @@
             w_ctype._lazy_ffi = ffi
             w_ctype._lazy_s = s
     else:
-        yyyy
+        x = _fetch_external_struct_or_union(s, ffi.included_libs)
+        if x is None:
+            raise oefmt(ffi.w_FFIError,
+                    "'%s %s' should come from ffi.include() but was not found",
+                    "union" if c_flags & cffi_opcode.F_UNION else "struct",
+                    rffi.charp2str(s.c_name))
 
     # Update the "primary" OP_STRUCT_UNION slot
     ffi.cached_types[type_index] = x
@@ -385,3 +390,27 @@
 
     w_ctype._lazy_ffi = None
     w_ctype._lazy_s = lltype.nullptr(parse_c_type.FIELD_S)
+
+
+def _fetch_external_struct_or_union(s, included_libs):
+    name = rffi.charp2str(s.c_name)
+    #
+    for lib1 in included_libs:
+        sindex = parse_c_type.search_in_struct_unions(lib1.ctx, name)
+        if sindex < 0:   # not found at all
+            continue
+
+        s1 = lib1.ctx.c_struct_unions[sindex]
+        s1_flags = rffi.getintfield(s1, 'c_flags')
+        s_flags  = rffi.getintfield(s,  'c_flags')
+        if ((s1_flags & (cffi_opcode.F_EXTERNAL | cffi_opcode.F_UNION))
+                == (s_flags & cffi_opcode.F_UNION)):
+            # s1 is not external, and the same kind (struct or union) as s
+            return _realize_c_struct_or_union(lib1.ffi, sindex)
+
+        # not found, look more recursively
+        if len(lib1.ffi.included_libs) > 0:
+            w_res = _fetch_external_struct_or_union(s, lib1.ffi.included_libs)
+            if w_res is not None:
+                return w_res
+    return None
diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py 
b/pypy/module/_cffi_backend/test/test_recompiler.py
--- a/pypy/module/_cffi_backend/test/test_recompiler.py
+++ b/pypy/module/_cffi_backend/test/test_recompiler.py
@@ -497,16 +497,17 @@
         assert lib.foo2(42) == 37
         assert lib.foo1(42) == 52
 
-    def test_include_2():
-        ffi1 = FFI()
-        ffi1.cdef("struct foo_s { int x, y; };")
-        verify(ffi1, "test_include_2_parent", "struct foo_s { int x, y; };")
-        ffi = FFI()
-        ffi.include(ffi1)
-        ffi.cdef("struct foo_s *ff2(struct foo_s *);")
-        lib = verify(ffi, "test_include_2",
-                     "struct foo_s { int x, y; }; //usually from a #include\n"
-                     "struct foo_s *ff2(struct foo_s *p) { p->y++; return p; 
}")
+    def test_include_2(self):
+        ffi1, lib1 = self.prepare(
+            "struct foo_s { int x, y; };",
+            "test_include_2_parent",
+            "struct foo_s { int x, y; };")
+        ffi, lib = self.prepare(
+            "struct foo_s *ff2(struct foo_s *);",
+            "test_include_2",
+            "struct foo_s { int x, y; }; //usually from a #include\n"
+            "struct foo_s *ff2(struct foo_s *p) { p->y++; return p; }",
+            includes=[ffi1])
         p = ffi.new("struct foo_s *")
         p.y = 41
         q = lib.ff2(p)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to