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

Reply via email to