[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