Author: Armin Rigo <ar...@tunes.org>
Branch: static-callback
Changeset: r2380:b506706f5a75
Date: 2015-11-13 13:12 +0100
http://bitbucket.org/cffi/cffi/changeset/b506706f5a75/

Log:    Finally found a way to arrange the generated code

diff --git a/cffi/parse_c_type.h b/cffi/parse_c_type.h
--- a/cffi/parse_c_type.h
+++ b/cffi/parse_c_type.h
@@ -160,6 +160,17 @@
     const char *error_message;
 };
 
+struct _cffi_callpy_s {
+    const char *name;
+    const struct _cffi_type_context_s *ctx;
+    int type_index;
+    void *direct_fn;
+    void *reserved;
+};
+
+extern void _cffi_call_python(struct _cffi_callpy_s *, void *);
+
+
 #ifdef _CFFI_INTERNAL
 static int parse_c_type(struct _cffi_parse_info_s *info, const char *input);
 static int search_in_globals(const struct _cffi_type_context_s *ctx,
diff --git a/cffi/recompiler.py b/cffi/recompiler.py
--- a/cffi/recompiler.py
+++ b/cffi/recompiler.py
@@ -227,6 +227,7 @@
         self._lsts = {}
         for step_name in self.ALL_STEPS:
             self._lsts[step_name] = []
+        self._callpy = []
         self._seen_struct_unions = set()
         self._generate("ctx")
         self._add_missing_struct_unions()
@@ -360,6 +361,9 @@
         prnt('};')
         prnt()
         #
+        if self._callpy:
+            self._generate_delayed_callpy()
+        #
         # the init function
         base_module_name = self.module_name.split('.')[-1]
         prnt('#ifdef PYPY_VERSION')
@@ -1108,6 +1112,71 @@
             GlobalExpr(name, '_cffi_var_%s' % name, CffiOp(op, type_index)))
 
     # ----------
+    # CFFI_CALL_PYTHON
+
+    def _generate_cpy_call_python_collecttype(self, tp, name):
+        self._do_collect_type(tp.as_raw_function())
+
+    def _generate_cpy_call_python_decl(self, tp, name):
+        pass    # the function is delayed and only generated later
+
+    def _generate_cpy_call_python_ctx(self, tp, name):
+        if self.target_is_python:
+            raise ffiplatform.VerificationError(
+                "cannot use CFFI_CALL_PYTHON in the ABI mode")
+        if tp.ellipsis:
+            raise NotImplementedError("CFFI_CALL_PYTHON with a vararg 
function")
+        self._callpy.append((tp, name))
+
+    def _generate_delayed_callpy(self):
+        #
+        # Write static headers for all the call-python functions
+        prnt = self._prnt
+        function_sigs = []
+        for tp, name in self._callpy:
+            arguments = []
+            context = 'argument of %s' % name
+            for i, type in enumerate(tp.args):
+                arg = type.get_c_name(' a%d' % i, context)
+                arguments.append(arg)
+            #
+            repr_arguments = ', '.join(arguments)
+            repr_arguments = repr_arguments or 'void'
+            name_and_arguments = '%s(%s)' % (name, repr_arguments)
+            context = 'result of %s' % name
+            sig = tp.result.get_c_name(name_and_arguments, context)
+            function_sigs.append(sig)
+            prnt('static %s;' % sig)
+        prnt()
+        #
+        # Write the _cffi_callpy array, which is not constant: a few
+        # fields (notably "reserved") can be modified by _cffi_backend
+        prnt('static struct _cffi_callpy_s _cffi_callpys[%d] = {' %
+             (len(self._callpy),))
+        for tp, name in self._callpy:
+            type_index = self._typesdict[tp.as_raw_function()]
+            prnt('  { "%s", &_cffi_type_context, %d, (void *)&%s },' % (
+                name, type_index, name))
+        prnt('};')
+        prnt()
+        #
+        # Write the implementation of the functions declared above
+        for (tp, name), sig in zip(self._callpy, function_sigs):
+            prnt('static %s' % sig)
+            prnt('{')
+            prnt('  uint64_t a[%d];' % max(len(tp.args), 1))
+            prnt('  char *p = (char *)a;')
+            for i, type in enumerate(tp.args):
+                prnt('  *(%s)(p + %d) = a%d;' % (type.get_c_name('*'), i*8, i))
+            prnt('  _cffi_call_python(_cffi_callpys + 0, a);')
+            if isinstance(tp.result, model.VoidType):
+                prnt('  (void)p;')
+            else:
+                prnt('  return *(%s)p;' % (tp.result.get_c_name('*'),))
+            prnt('}')
+            prnt()
+
+    # ----------
     # emitting the opcodes for individual types
 
     def _emit_bytecode_VoidType(self, tp, index):
diff --git a/testing/cffi1/test_recompiler.py b/testing/cffi1/test_recompiler.py
--- a/testing/cffi1/test_recompiler.py
+++ b/testing/cffi1/test_recompiler.py
@@ -1484,3 +1484,14 @@
     assert (pt.x, pt.y) == (99*500*999, -99*500*999)
     pt = ptr_call2(ffi.addressof(lib, 'cb2'))
     assert (pt.x, pt.y) == (99*500*999, -99*500*999)
+
+def test_call_python_1():
+    ffi = FFI()
+    ffi.cdef("""
+        CFFI_CALL_PYTHON int bar(int, int);
+        CFFI_CALL_PYTHON void baz(int, int);
+        CFFI_CALL_PYTHON int bok(void);
+        CFFI_CALL_PYTHON void boz(void);
+    """)
+    lib = verify(ffi, 'test_call_python_1', "")
+    XXX
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to