[pypy-commit] cffi cffi-1.0: The ``cffi_modules = ["module:ffi"]`` can now also name a global
arigo
noreply at buildbot.pypy.org
Sat May 9 14:27:38 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1946:13a728b641ba
Date: 2015-05-09 14:28 +0200
http://bitbucket.org/cffi/cffi/changeset/13a728b641ba/
Log: The ``cffi_modules = ["module:ffi"]`` can now also name a global
function instead of an FFI object; the function is then called with
no arguments.
diff --git a/_cffi1/recompiler.py b/_cffi1/recompiler.py
--- a/_cffi1/recompiler.py
+++ b/_cffi1/recompiler.py
@@ -386,16 +386,16 @@
argname = 'arg0'
else:
argname = 'args'
+ #
prnt('#ifndef PYPY_VERSION') # ------------------------------
+ #
prnt('static PyObject *')
prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname))
prnt('{')
#
context = 'argument of %s' % name
- arguments = []
for i, type in enumerate(tp.args):
arg = type.get_c_name(' x%d' % i, context)
- arguments.append(arg)
prnt(' %s;' % arg)
#
localvars = set()
@@ -432,8 +432,7 @@
prnt(' _cffi_restore_errno();')
call_arguments = ['x%d' % i for i in range(len(tp.args))]
call_arguments = ', '.join(call_arguments)
- call_code = ' { %s%s(%s); }' % (result_code, name, call_arguments)
- prnt(call_code)
+ prnt(' { %s%s(%s); }' % (result_code, name, call_arguments))
prnt(' _cffi_save_errno();')
prnt(' Py_END_ALLOW_THREADS')
prnt()
@@ -448,7 +447,21 @@
prnt(' Py_INCREF(Py_None);')
prnt(' return Py_None;')
prnt('}')
+ #
prnt('#else') # ------------------------------
+ #
+ # the PyPy version: need to replace struct/union arguments with
+ # pointers, and if the result is a struct/union, insert a first
+ # arg that is a pointer to the result.
+ arguments = []
+ call_arguments = []
+ for i, type in enumerate(tp.args):
+ indirection = ''
+ if isinstance(type, model.StructOrUnion):
+ indirection = '*'
+ arg = type.get_c_name(' %sx%d' % (indirection, i), context)
+ arguments.append(arg)
+ call_arguments.append('%sx%d' % (indirection, i))
repr_arguments = ', '.join(arguments)
repr_arguments = repr_arguments or 'void'
name_and_arguments = '_cffi_f_%s(%s)' % (name, repr_arguments)
@@ -456,10 +469,12 @@
prnt('{')
if result_decl:
prnt(result_decl)
- prnt(call_code)
+ call_arguments = ', '.join(call_arguments)
+ prnt(' { %s%s(%s); }' % (result_code, name, call_arguments))
if result_decl:
prnt(' return result;')
prnt('}')
+ #
prnt('#endif') # ------------------------------
prnt()
diff --git a/_cffi1/setuptools_ext.py b/_cffi1/setuptools_ext.py
--- a/_cffi1/setuptools_ext.py
+++ b/_cffi1/setuptools_ext.py
@@ -34,6 +34,8 @@
error("%r: object %r not found in module" % (mod_spec,
ffi_var_name))
if not isinstance(ffi, FFI):
+ ffi = ffi() # maybe it's a function instead of directly an ffi
+ if not isinstance(ffi, FFI):
error("%r is not an FFI instance (got %r)" % (mod_spec,
type(ffi).__name__))
if not hasattr(ffi, '_assigned_source'):
diff --git a/_cffi1/test_recompiler.py b/_cffi1/test_recompiler.py
--- a/_cffi1/test_recompiler.py
+++ b/_cffi1/test_recompiler.py
@@ -627,3 +627,24 @@
lib = verify(ffi, 'test_math_sin_unicode', unicode('#include <math.h>'),
libraries=[unicode(lib_m)])
assert lib.cos(1.43) == math.cos(1.43)
+
+def test_incomplete_struct_as_arg():
+ ffi = FFI()
+ ffi.cdef("struct foo_s { int x; ...; }; int f(struct foo_s);")
+ lib = verify(ffi, "test_incomplete_struct_as_arg",
+ "struct foo_s { int a, x, z; };\n"
+ "int f(struct foo_s s) { return s.x * 2; }")
+ s = ffi.new("struct foo_s *", [21])
+ assert s.x == 21
+ assert ffi.sizeof(s[0]) == 12
+ assert ffi.offsetof(ffi.typeof(s), 'x') == 4
+ assert lib.f(s[0]) == 42
+
+def test_incomplete_struct_as_result():
+ ffi = FFI()
+ ffi.cdef("struct foo_s { int x; ...; }; struct foo_s f(int);")
+ lib = verify(ffi, "test_incomplete_struct_as_result",
+ "struct foo_s { int a, x, z; };\n"
+ "struct foo_s f(int x) { struct foo_s r; r.x = x * 2; return r; }")
+ s = lib.f(21)
+ assert s.x == 42
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -4255,8 +4255,9 @@
return NULL;
if (ct->ct_flags & CT_CUSTOM_FIELD_POS) {
PyErr_SetString(PyExc_TypeError,
- "cannot pass as an argument a struct that was completed "
- "with verify() (see _cffi_backend.c for details of why)");
+ "argument or return value is a struct (not pointer to struct) "
+ "which was declared with \"...;\" --- but the C calling "
+ "convention can depend on the missing fields");
return NULL;
}
More information about the pypy-commit
mailing list