[pypy-commit] cffi default: issue 102: allow ffi.typeof() to work on functions taking a struct

arigo noreply at buildbot.pypy.org
Wed Sep 11 14:36:16 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r1347:199010759f60
Date: 2013-09-11 14:35 +0200
http://bitbucket.org/cffi/cffi/changeset/199010759f60/

Log:	issue 102: allow ffi.typeof() to work on functions taking a struct
	argument (with vengine_gen). Note that it still fails on functions
	taking an auto-completed struct. Unsure if and how to fix.

diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -144,6 +144,9 @@
             res = _builtin_function_type(cdecl)
             if res is not None:
                 return res
+        if (isinstance(cdecl, types.FunctionType)
+                and hasattr(cdecl, '_cffi_base_type')):
+            return self._get_cached_btype(cdecl._cffi_base_type)
         raise TypeError(type(cdecl))
 
     def sizeof(self, cdecl):
diff --git a/cffi/vengine_gen.py b/cffi/vengine_gen.py
--- a/cffi/vengine_gen.py
+++ b/cffi/vengine_gen.py
@@ -173,6 +173,7 @@
             newfunction = self._load_constant(False, tp, name, module)
         else:
             indirections = []
+            base_tp = tp
             if any(isinstance(typ, model.StructOrUnion) for typ in tp.args):
                 indirect_args = []
                 for i, typ in enumerate(tp.args):
@@ -186,16 +187,18 @@
             wrappername = '_cffi_f_%s' % name
             newfunction = module.load_function(BFunc, wrappername)
             for i, typ in indirections:
-                newfunction = self._make_struct_wrapper(newfunction, i, typ)
+                newfunction = self._make_struct_wrapper(newfunction, i, typ,
+                                                        base_tp)
         setattr(library, name, newfunction)
         type(library)._cffi_dir.append(name)
 
-    def _make_struct_wrapper(self, oldfunc, i, tp):
+    def _make_struct_wrapper(self, oldfunc, i, tp, base_tp):
         backend = self.ffi._backend
         BType = self.ffi._get_cached_btype(tp)
         def newfunc(*args):
             args = args[:i] + (backend.newp(BType, args[i]),) + args[i+1:]
             return oldfunc(*args)
+        newfunc._cffi_base_type = base_tp
         return newfunc
 
     # ----------
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -1634,3 +1634,13 @@
                         #define FOO 42""")
     assert dir(lib) == ['AA', 'BB', 'FOO', 'somearray',
                         'somefunc', 'somevar', 'sv2']
+
+def test_typeof_func_with_struct_argument():
+    ffi = FFI()
+    ffi.cdef("""struct s { int a; }; int foo(struct s);""")
+    lib = ffi.verify("""struct s { int a; };
+                        int foo(struct s x) { return x.a; }""")
+    s = ffi.new("struct s *", [-1234])
+    m = lib.foo(s[0])
+    assert m == -1234
+    assert repr(ffi.typeof(lib.foo)) == "<ctype 'int(*)(struct s)'>"


More information about the pypy-commit mailing list