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