Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit