Author: Armin Rigo <[email protected]>
Branch: static-callback
Changeset: r2386:716fcb19c96a
Date: 2015-11-13 15:34 +0100
http://bitbucket.org/cffi/cffi/changeset/716fcb19c96a/
Log: tweak tweak tweak until we can at least read the function pointer
out of the 'lib' object
diff --git a/c/lib_obj.c b/c/lib_obj.c
--- a/c/lib_obj.c
+++ b/c/lib_obj.c
@@ -364,6 +364,16 @@
break;
}
+ case _CFFI_OP_CALL_PYTHON:
+ /* for reading 'lib.bar' where bar is declared with CFFI_CALL_PYTHON */
+ ct = realize_c_type(types_builder, types_builder->ctx.types,
+ _CFFI_GETARG(g->type_op));
+ if (ct == NULL)
+ return NULL;
+ x = convert_to_object(g->address, ct);
+ Py_DECREF(ct);
+ break;
+
default:
PyErr_Format(PyExc_NotImplementedError, "in lib_build_attr: op=%d",
(int)_CFFI_GETOP(g->type_op));
diff --git a/cffi/_cffi_include.h b/cffi/_cffi_include.h
--- a/cffi/_cffi_include.h
+++ b/cffi/_cffi_include.h
@@ -146,7 +146,9 @@
((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23])
#define _cffi_convert_array_from_object \
((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24])
-#define _CFFI_NUM_EXPORTS 25
+#define _cffi_call_python \
+ ((void(*)(struct _cffi_callpy_s *, char *))_cffi_exports[25])
+#define _CFFI_NUM_EXPORTS 26
typedef struct _ctypedescr CTypeDescrObject;
@@ -201,8 +203,10 @@
the others follow */
}
+/********** end CPython-specific section **********/
+#else
+extern void _cffi_call_python(struct _cffi_callpy_s *, char *);
#endif
-/********** end CPython-specific section **********/
#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0]))
diff --git a/cffi/cffi_opcode.py b/cffi/cffi_opcode.py
--- a/cffi/cffi_opcode.py
+++ b/cffi/cffi_opcode.py
@@ -54,6 +54,7 @@
OP_DLOPEN_FUNC = 35
OP_DLOPEN_CONST = 37
OP_GLOBAL_VAR_F = 39
+OP_CALL_PYTHON = 41
PRIM_VOID = 0
PRIM_BOOL = 1
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
@@ -27,6 +27,7 @@
#define _CFFI_OP_DLOPEN_FUNC 35
#define _CFFI_OP_DLOPEN_CONST 37
#define _CFFI_OP_GLOBAL_VAR_F 39
+#define _CFFI_OP_CALL_PYTHON 41
#define _CFFI_PRIM_VOID 0
#define _CFFI_PRIM_BOOL 1
@@ -162,15 +163,11 @@
struct _cffi_callpy_s {
const char *name;
- const struct _cffi_type_context_s *ctx;
int type_index;
- void *direct_fn;
- void *reserved;
+ int reserved1;
+ void *reserved2, *reserved3;
};
-extern void _cffi_call_python(struct _cffi_callpy_s *, char *);
-
-
#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,7 +227,6 @@
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()
@@ -361,9 +360,6 @@
prnt('};')
prnt()
#
- if self._callpy:
- self._generate_delayed_callpy()
- #
# the init function
base_module_name = self.module_name.split('.')[-1]
prnt('#ifdef PYPY_VERSION')
@@ -1115,10 +1111,54 @@
# CFFI_CALL_PYTHON
def _generate_cpy_call_python_collecttype(self, tp, name):
- self._do_collect_type(tp.as_raw_function())
+ assert isinstance(tp, model.FunctionPtrType)
+ self._do_collect_type(tp)
def _generate_cpy_call_python_decl(self, tp, name):
- pass # the function is delayed and only generated later
+ prnt = self._prnt
+ type_index = self._typesdict[tp.as_raw_function()]
+ prnt('static struct _cffi_callpy_s _cffi_callpy__%s = { "%s", %d };' %
(
+ name, name, type_index))
+ prnt()
+ #
+ 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)
+ #
+ def may_need_128_bits(tp):
+ return (isinstance(tp, model.PrimitiveType) and
+ tp.name == 'long double')
+ #
+ size_of_a = max(len(tp.args)*8, 8)
+ if may_need_128_bits(tp.result):
+ size_of_a = max(size_of_a, 16)
+ if isinstance(tp.result, model.StructOrUnion):
+ size_of_a = 'sizeof(%s) > %d ? sizeof(%s) : %d' % (
+ tp.result.get_c_name(''), size_of_a,
+ tp.result.get_c_name(''), size_of_a)
+ context = 'result of %s' % name
+ prnt('static %s' % tp.result.get_c_name(name_and_arguments, context))
+ prnt('{')
+ prnt(' char a[%s];' % size_of_a)
+ prnt(' char *p = a;')
+ for i, type in enumerate(tp.args):
+ arg = 'a%d' % i
+ if (isinstance(type, model.StructOrUnion) or
+ may_need_128_bits(type)):
+ arg = '&' + arg
+ type = model.PointerType(type)
+ prnt(' *(%s)(p + %d) = %s;' % (type.get_c_name('*'), i*8, arg))
+ prnt(' _cffi_call_python(&_cffi_callpy__%s, p);' % name)
+ if not isinstance(tp.result, model.VoidType):
+ prnt(' return *(%s)p;' % (tp.result.get_c_name('*'),))
+ prnt('}')
+ prnt()
def _generate_cpy_call_python_ctx(self, tp, name):
if self.target_is_python:
@@ -1126,70 +1166,10 @@
"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
- def may_need_128_bits(tp):
- return (isinstance(tp, model.PrimitiveType) and
- tp.name == 'long double')
- #
- for j in range(len(self._callpy)):
- tp, name = self._callpy[j]
- size_of_a = max(len(tp.args)*8, 8)
- if may_need_128_bits(tp.result):
- size_of_a = max(size_of_a, 16)
- if isinstance(tp.result, model.StructOrUnion):
- size_of_a = 'sizeof(%s) > %d ? sizeof(%s) : %d' % (
- tp.result.get_c_name(''), size_of_a,
- tp.result.get_c_name(''), size_of_a)
- prnt('static %s' % function_sigs[j])
- prnt('{')
- prnt(' char a[%s];' % size_of_a)
- prnt(' char *p = a;')
- for i, type in enumerate(tp.args):
- arg = 'a%d' % i
- if (isinstance(type, model.StructOrUnion) or
- may_need_128_bits(type)):
- arg = '&' + arg
- type = model.PointerType(type)
- prnt(' *(%s)(p + %d) = %s;' % (type.get_c_name('*'), i*8,
arg))
- prnt(' _cffi_call_python(_cffi_callpys + %d, p);' % j)
- if not isinstance(tp.result, model.VoidType):
- prnt(' return *(%s)p;' % (tp.result.get_c_name('*'),))
- prnt('}')
- prnt()
+ type_index = self._typesdict[tp]
+ type_op = CffiOp(OP_CALL_PYTHON, type_index)
+ self._lsts["global"].append(
+ GlobalExpr(name, name, type_op, '&_cffi_callpy__%s' % name))
# ----------
# emitting the opcodes for individual types
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
@@ -1494,6 +1494,7 @@
CFFI_CALL_PYTHON void boz(void);
""")
lib = verify(ffi, 'test_call_python_1', "")
+ assert ffi.typeof(lib.bar) == ffi.typeof("int(*)(int, int)")
XXX
def test_call_python_2():
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit