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