[pypy-commit] cffi cffi-1.0: next test and fix

arigo noreply at buildbot.pypy.org
Fri Apr 17 17:39:40 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1743:1a738a27aa65
Date: 2015-04-17 17:40 +0200
http://bitbucket.org/cffi/cffi/changeset/1a738a27aa65/

Log:	next test and fix

diff --git a/new/_cffi_include.h b/new/_cffi_include.h
--- a/new/_cffi_include.h
+++ b/new/_cffi_include.h
@@ -155,6 +155,10 @@
 
 static void *_cffi_exports[_CFFI_NUM_EXPORTS];
 
+#define _cffi_type(index)   (                           \
+    assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \
+    (CTypeDescrObject *)_cffi_types[index])
+
 
 static int _cffi_init(void)
 {
diff --git a/new/ffi_obj.c b/new/ffi_obj.c
--- a/new/ffi_obj.c
+++ b/new/ffi_obj.c
@@ -135,18 +135,22 @@
         }
         CTypeDescrObject *ct = realize_c_type(ffi->types_builder,
                                               ffi->info.output, index);
-        if (ct != NULL) {
-            /* Cache under the name given by 'arg', in addition to the
-               fact that the same ct is probably already cached under
-               its standardized name.  In a few cases, it is not, e.g.
-               if it is a primitive; for the purpose of this function,
-               the important point is the following line, which makes
-               sure that in any case the next _ffi_type() with the same
-               'arg' will succeed early, in PyDict_GetItem() above.
-            */
-            if (PyDict_SetItem(types_dict, arg, (PyObject *)ct) < 0)
-                return NULL;
-        }
+        if (ct == NULL)
+            return NULL;
+
+        /* Cache under the name given by 'arg', in addition to the
+           fact that the same ct is probably already cached under
+           its standardized name.  In a few cases, it is not, e.g.
+           if it is a primitive; for the purpose of this function,
+           the important point is the following line, which makes
+           sure that in any case the next _ffi_type() with the same
+           'arg' will succeed early, in PyDict_GetItem() above.
+        */
+        int err = PyDict_SetItem(types_dict, arg, (PyObject *)ct);
+        Py_DECREF(ct);   /* we know it was written in types_dict (unless we got
+                     out of memory), so there is at least this reference left */
+        if (err < 0)
+            return NULL;
         return ct;
     }
     else if ((accept & ACCEPT_CTYPE) && CTypeDescr_Check(arg)) {
diff --git a/new/lib_obj.c b/new/lib_obj.c
--- a/new/lib_obj.c
+++ b/new/lib_obj.c
@@ -43,6 +43,32 @@
                                         const struct _cffi_global_s *g,
                                         const char *s, int flags)
 {
+    /* First make sure the argument types and return type are really
+       built.  The C extension code can then assume that they are,
+       by calling _cffi_type().
+    */
+    CTypeDescrObject *ct;
+    int type_index = _CFFI_GETARG(g->type_op);
+    _cffi_opcode_t *opcodes = lib->l_types_builder->ctx.types;
+    assert(_CFFI_GETOP(opcodes[type_index]) == _CFFI_OP_FUNCTION);
+
+    /* return type: */
+    ct = realize_c_type(lib->l_types_builder, opcodes,
+                        _CFFI_GETARG(opcodes[type_index]));
+    if (ct == NULL)
+        return NULL;
+    Py_DECREF(ct);
+
+    /* argument types: */
+    int i = type_index + 1;
+    while (_CFFI_GETOP(opcodes[i]) != _CFFI_OP_FUNCTION_END) {
+        ct = realize_c_type(lib->l_types_builder, opcodes, i);
+        if (ct == NULL)
+            return NULL;
+        Py_DECREF(ct);
+        i++;
+    }
+
     /* xxx the few bytes of memory we allocate here leak, but it's a
        minor concern because it should only occur for CPYTHON_BLTN.
        There is one per real C function in a CFFI C extension module.
@@ -60,7 +86,7 @@
         goto no_memory;
 
     xfunc->types_builder = lib->l_types_builder;
-    xfunc->type_index = _CFFI_GETARG(g->type_op);
+    xfunc->type_index = type_index;
 
     return PyCFunction_NewEx(&xfunc->md, NULL, lib->l_libname);
 
diff --git a/new/recompiler.py b/new/recompiler.py
--- a/new/recompiler.py
+++ b/new/recompiler.py
@@ -215,7 +215,7 @@
     def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode):
         self._prnt('  datasize = _cffi_prepare_pointer_call_argument(')
         self._prnt('      _cffi_type(%d), %s, (char **)&%s);' % (
-            self._gettypenum(tp), fromvar, tovar))
+            self._typesdict[tp], fromvar, tovar))
         self._prnt('  if (datasize != 0) {')
         self._prnt('    if (datasize < 0)')
         self._prnt('      %s;' % errcode)
@@ -223,7 +223,7 @@
         self._prnt('    memset((void *)%s, 0, (size_t)datasize);' % (tovar,))
         self._prnt('    if (_cffi_convert_array_from_object('
                    '(char *)%s, _cffi_type(%d), %s) < 0)' % (
-            tovar, self._gettypenum(tp), fromvar))
+            tovar, self._typesdict[tp], fromvar))
         self._prnt('      %s;' % errcode)
         self._prnt('  }')
 
diff --git a/new/test_recompiler.py b/new/test_recompiler.py
--- a/new/test_recompiler.py
+++ b/new/test_recompiler.py
@@ -1,14 +1,19 @@
 import py
-from recompiler import Recompiler, verify
+import recompiler
 from cffi1 import FFI
 
 
 def check_type_table(input, expected_output):
     ffi = FFI()
     ffi.cdef(input)
-    recompiler = Recompiler(ffi, 'testmod')
-    recompiler.collect_type_table()
-    assert ''.join(map(str, recompiler.cffi_types)) == expected_output
+    recomp = recompiler.Recompiler(ffi, 'testmod')
+    recomp.collect_type_table()
+    assert ''.join(map(str, recomp.cffi_types)) == expected_output
+
+def verify(*args, **kwds):
+    kwds.setdefault('undef_macros', ['NDEBUG'])
+    return recompiler.verify(*args, **kwds)
+
 
 def test_type_table_func():
     check_type_table("double sin(double);",
@@ -86,6 +91,12 @@
     lib = verify(ffi, 'test_math_sin', '#include <math.h>')
     assert lib.cos(1.43) == math.cos(1.43)
 
+def test_funcarg_ptr():
+    ffi = FFI()
+    ffi.cdef("int foo(int *);")
+    lib = verify(ffi, 'test_funcarg_ptr', 'int foo(int *p) { return *p; }')
+    assert lib.foo([-12345]) == -12345
+
 def test_global_var_array():
     ffi = FFI()
     ffi.cdef("int a[100];")


More information about the pypy-commit mailing list