Author: Romain Guillebert <[email protected]>
Branch:
Changeset: r1592:9267d5f13672
Date: 2014-12-17 18:04 +0100
http://bitbucket.org/cffi/cffi/changeset/9267d5f13672/
Log: Merge heads
diff --git a/TODO b/TODO
--- a/TODO
+++ b/TODO
@@ -1,10 +1,3 @@
-Next steps
-----------
-
-verify() handles "typedef ... some_integer_type", but this creates
-an opaque type that works like a struct (so we can't get the value
-out of it).
-
-accept and kill "static inline" in the cdefs
+Add other required types from stdint.h
diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -4765,7 +4765,7 @@
CFieldObject *cf;
Py_ssize_t offset;
- if (!PyArg_ParseTuple(args, "O!O:typeof",
+ if (!PyArg_ParseTuple(args, "O!O:typeoffsetof",
&CTypeDescr_Type, &ct, &fieldname))
return NULL;
diff --git a/cffi/cparser.py b/cffi/cparser.py
--- a/cffi/cparser.py
+++ b/cffi/cparser.py
@@ -208,6 +208,8 @@
def _add_constants(self, key, val):
if key in self._int_constants:
+ if self._int_constants[key] == val:
+ return # ignore identical double declarations
raise api.FFIError(
"multiple declarations of constant: %s" % (key,))
self._int_constants[key] = val
diff --git a/cffi/vengine_cpy.py b/cffi/vengine_cpy.py
--- a/cffi/vengine_cpy.py
+++ b/cffi/vengine_cpy.py
@@ -235,7 +235,8 @@
converter = '_cffi_to_c_int'
extraarg = ', %s' % tp.name
else:
- converter = '_cffi_to_c_%s' % (tp.name.replace(' ', '_'),)
+ converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''),
+ tp.name.replace(' ', '_'))
errvalue = '-1'
#
elif isinstance(tp, model.PointerType):
@@ -274,8 +275,8 @@
self._prnt(' if (datasize != 0) {')
self._prnt(' if (datasize < 0)')
self._prnt(' %s;' % errcode)
- self._prnt(' %s = alloca(datasize);' % (tovar,))
- self._prnt(' memset((void *)%s, 0, datasize);' % (tovar,))
+ self._prnt(' %s = alloca((size_t)datasize);' % (tovar,))
+ 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))
@@ -835,12 +836,15 @@
PyLong_FromLongLong((long long)(x)))
#define _cffi_from_c_int(x, type) \
- (((type)-1) > 0 ? /* unsigned */ \
- (sizeof(type) < sizeof(long) ? PyInt_FromLong(x) : \
- sizeof(type) == sizeof(long) ? PyLong_FromUnsignedLong(x) : \
- PyLong_FromUnsignedLongLong(x)) \
- : (sizeof(type) <= sizeof(long) ? PyInt_FromLong(x) : \
- PyLong_FromLongLong(x)))
+ (((type)-1) > 0 ? /* unsigned */ \
+ (sizeof(type) < sizeof(long) ? \
+ PyInt_FromLong((long)x) : \
+ sizeof(type) == sizeof(long) ? \
+ PyLong_FromUnsignedLong((unsigned long)x) : \
+ PyLong_FromUnsignedLongLong((unsigned long long)x)) : \
+ (sizeof(type) <= sizeof(long) ? \
+ PyInt_FromLong((long)x) : \
+ PyLong_FromLongLong((long long)x)))
#define _cffi_to_c_int(o, type) \
(sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \
@@ -851,7 +855,7 @@
: (type)_cffi_to_c_i32(o)) : \
sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \
: (type)_cffi_to_c_i64(o)) : \
- (Py_FatalError("unsupported size for type " #type), 0))
+ (Py_FatalError("unsupported size for type " #type), (type)0))
#define _cffi_to_c_i8 \
((int(*)(PyObject *))_cffi_exports[1])
diff --git a/cffi/verifier.py b/cffi/verifier.py
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -16,7 +16,8 @@
class Verifier(object):
def __init__(self, ffi, preamble, tmpdir=None, modulename=None,
- ext_package=None, tag='', force_generic_engine=False,
flags=None, **kwds):
+ ext_package=None, tag='', force_generic_engine=False,
+ source_extension='.c', flags=None, **kwds):
self.ffi = ffi
self.preamble = preamble
if not modulename:
@@ -44,7 +45,7 @@
k1, k2)
suffix = _get_so_suffixes()[0]
self.tmpdir = tmpdir or os.environ.get('CFFI_TMPDIR') or
_caller_dir_pycache()
- self.sourcefilename = os.path.join(self.tmpdir, modulename + '.c')
+ self.sourcefilename = os.path.join(self.tmpdir, modulename +
source_extension)
self.modulefilename = os.path.join(self.tmpdir, modulename + suffix)
self.ext_package = ext_package
self._has_source = False
diff --git a/doc/source/index.rst b/doc/source/index.rst
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -667,7 +667,16 @@
check. Be sure to have other means of clearing the ``tmpdir``
whenever you change your sources.
-.. versionadded:: 0.9
+.. versionadded:: 0.8.7
+ You can give C++ source code in ``ffi.verify()``::
+
+ ext = ffi.verify(r'''
+ extern "C" {
+ int somefunc(int somearg) { return real_cpp_func(somearg); }
+ }
+ ''', source_extension='.cpp', extra_compile_args=['-std=c++11'])
+
+.. versionadded:: 0.8.7
The optional ``flags`` argument has been added, see ``man dlopen`` (ignored
on Windows). It defaults to ``ffi.RTLD_NOW``.
@@ -863,7 +872,9 @@
.. versionadded:: 0.8.2
The ``ffi.cdef()`` call takes an optional argument ``packed``: if
- True, then all structs declared within this cdef are "packed". This
+ True, then all structs declared within this cdef are "packed".
+ (If you need both packed and non-packed structs,
+ use several cdefs in sequence.) This
has a meaning similar to ``__attribute__((packed))`` in GCC. It
specifies that all structure fields should have an alignment of one
byte. (Note that the packed attribute has no effect on bit fields so
diff --git a/testing/backend_tests.py b/testing/backend_tests.py
--- a/testing/backend_tests.py
+++ b/testing/backend_tests.py
@@ -1,7 +1,7 @@
import py
import platform
import sys, ctypes
-from cffi import FFI, CDefError
+from cffi import FFI, CDefError, FFIError
from testing.support import *
SIZE_OF_INT = ctypes.sizeof(ctypes.c_int)
@@ -1564,6 +1564,12 @@
p = ffi2.new("foo_p", [142])
assert p.x == 142
+ def test_ignore_multiple_declarations_of_constant(self):
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("#define FOO 42")
+ ffi.cdef("#define FOO 42")
+ py.test.raises(FFIError, ffi.cdef, "#define FOO 43")
+
def test_struct_packed(self):
ffi = FFI(backend=self.Backend())
ffi.cdef("struct nonpacked { char a; int b; };")
diff --git a/testing/test_verify.py b/testing/test_verify.py
--- a/testing/test_verify.py
+++ b/testing/test_verify.py
@@ -14,12 +14,13 @@
else:
if (sys.platform == 'darwin' and
[int(x) for x in os.uname()[2].split('.')] >= [11, 0, 0]):
+ # assume a standard clang or gcc
+ extra_compile_args = ['-Werror', '-Wconversion']
# special things for clang
- extra_compile_args = [
- '-Werror', '-Qunused-arguments', '-Wno-error=shorten-64-to-32']
+ extra_compile_args.append('-Qunused-arguments')
else:
# assume a standard gcc
- extra_compile_args = ['-Werror']
+ extra_compile_args = ['-Werror', '-Wconversion']
class FFI(FFI):
def verify(self, *args, **kwds):
@@ -89,11 +90,48 @@
lib = ffi.verify('#include <math.h>', libraries=lib_m)
assert lib.sin(1.23) == math.sin(1.23)
+def _Wconversion(cdef, source, **kargs):
+ if sys.platform == 'win32':
+ py.test.skip("needs GCC or Clang")
+ ffi = FFI()
+ ffi.cdef(cdef)
+ py.test.raises(VerificationError, ffi.verify, source, **kargs)
+ extra_compile_args_orig = extra_compile_args[:]
+ extra_compile_args.remove('-Wconversion')
+ try:
+ lib = ffi.verify(source, **kargs)
+ finally:
+ extra_compile_args[:] = extra_compile_args_orig
+ return lib
+
+def test_Wconversion_unsigned():
+ _Wconversion("unsigned foo(void);",
+ "int foo(void) { return -1;}")
+
+def test_Wconversion_integer():
+ _Wconversion("short foo(void);",
+ "long long foo(void) { return 1<<sizeof(short);}")
+
+def test_Wconversion_floating():
+ lib = _Wconversion("float sin(double);",
+ "#include <math.h>", libraries=lib_m)
+ res = lib.sin(1.23)
+ assert res != math.sin(1.23) # not exact, because of double->float
+ assert abs(res - math.sin(1.23)) < 1E-5
+
+def test_Wconversion_float2int():
+ _Wconversion("int sinf(float);",
+ "#include <math.h>", libraries=lib_m)
+
+def test_Wconversion_double2int():
+ _Wconversion("int sin(double);",
+ "#include <math.h>", libraries=lib_m)
+
def test_rounding_1():
ffi = FFI()
- ffi.cdef("float sin(double x);")
+ ffi.cdef("double sinf(float x);")
lib = ffi.verify('#include <math.h>', libraries=lib_m)
- res = lib.sin(1.23)
+ res = lib.sinf(1.23)
assert res != math.sin(1.23) # not exact, because of double->float
assert abs(res - math.sin(1.23)) < 1E-5
@@ -112,14 +150,21 @@
assert lib.strlen(b"hi there!") == 9
def test_strlen_approximate():
- ffi = FFI()
- ffi.cdef("int strlen(char *s);")
- lib = ffi.verify("#include <string.h>")
+ lib = _Wconversion("int strlen(char *s);",
+ "#include <string.h>")
assert lib.strlen(b"hi there!") == 9
+def test_return_approximate():
+ for typename in ['short', 'int', 'long', 'long long']:
+ ffi = FFI()
+ ffi.cdef("%s foo(signed char x);" % typename)
+ lib = ffi.verify("signed char foo(signed char x) { return x;}")
+ assert lib.foo(-128) == -128
+ assert lib.foo(+127) == +127
+
def test_strlen_array_of_char():
ffi = FFI()
- ffi.cdef("int strlen(char[]);")
+ ffi.cdef("size_t strlen(char[]);")
lib = ffi.verify("#include <string.h>")
assert lib.strlen(b"hello") == 5
@@ -208,8 +253,8 @@
ffi = FFI()
ffi.cdef('\n'.join(["%s foo_%s(%s);" % (tp, tp.replace(' ', '_'), tp)
for tp in typenames]))
- lib = ffi.verify('\n'.join(["%s foo_%s(%s x) { return x+1; }" %
- (tp, tp.replace(' ', '_'), tp)
+ lib = ffi.verify('\n'.join(["%s foo_%s(%s x) { return (%s)(x+1); }" %
+ (tp, tp.replace(' ', '_'), tp, tp)
for tp in typenames]))
for typename in typenames:
foo = getattr(lib, 'foo_%s' % typename.replace(' ', '_'))
@@ -315,7 +360,7 @@
def test_char_type():
ffi = FFI()
ffi.cdef("char foo(char);")
- lib = ffi.verify("char foo(char x) { return x+1; }")
+ lib = ffi.verify("char foo(char x) { return ++x; }")
assert lib.foo(b"A") == b"B"
py.test.raises(TypeError, lib.foo, b"bar")
py.test.raises(TypeError, lib.foo, "bar")
@@ -896,7 +941,7 @@
static int foo(token_t *tk) {
if (!tk)
return -42;
- *tk += 1.601;
+ *tk += 1.601f;
return (int)*tk;
}
#define TOKEN_SIZE sizeof(token_t)
@@ -991,7 +1036,7 @@
long a;
};
int foo(struct foo_s s) {
- return s.a - (int)s.b;
+ return (int)s.a - (int)s.b;
}
""")
s = ffi.new("struct foo_s *", [100, 1])
@@ -1008,7 +1053,7 @@
long a;
};
int foo1(struct foo_s s) {
- return s.a - (int)s.b;
+ return (int)s.a - (int)s.b;
}
int (*foo)(struct foo_s s) = &foo1;
""")
@@ -1067,7 +1112,7 @@
def test_array_as_argument():
ffi = FFI()
ffi.cdef("""
- int strlen(char string[]);
+ size_t strlen(char string[]);
""")
ffi.verify("#include <string.h>")
@@ -1079,7 +1124,7 @@
""")
lib = ffi.verify("""
enum foo_e { AA, CC, BB };
- int foo_func(enum foo_e e) { return e; }
+ int foo_func(enum foo_e e) { return (int)e; }
""")
assert lib.foo_func(lib.BB) == 2
py.test.raises(TypeError, lib.foo_func, "BB")
@@ -1092,7 +1137,7 @@
""")
lib = ffi.verify("""
enum foo_e { AA, CC, BB };
- enum foo_e foo_func(int x) { return x; }
+ enum foo_e foo_func(int x) { return (enum foo_e)x; }
""")
assert lib.foo_func(lib.BB) == lib.BB == 2
@@ -1127,6 +1172,19 @@
assert lib.AA == 0
assert lib.BB == 2
+def test_typedef_enum_as_argument():
+ ffi = FFI()
+ ffi.cdef("""
+ typedef enum { AA, BB, ... } foo_t;
+ int foo_func(foo_t);
+ """)
+ lib = ffi.verify("""
+ typedef enum { AA, CC, BB } foo_t;
+ int foo_func(foo_t e) { return (int)e; }
+ """)
+ assert lib.foo_func(lib.BB) == lib.BB == 2
+ py.test.raises(TypeError, lib.foo_func, "BB")
+
def test_typedef_enum_as_function_result():
ffi = FFI()
ffi.cdef("""
@@ -1135,7 +1193,7 @@
""")
lib = ffi.verify("""
typedef enum { AA, CC, BB } foo_t;
- foo_t foo_func(int x) { return x; }
+ foo_t foo_func(int x) { return (foo_t)x; }
""")
assert lib.foo_func(lib.BB) == lib.BB == 2
@@ -1676,7 +1734,7 @@
static int c_callback(int how_many, ...) {
va_list ap;
/* collect the "..." arguments into the values[] array */
- int i, *values = alloca(how_many * sizeof(int));
+ int i, *values = alloca((size_t)how_many * sizeof(int));
va_start(ap, how_many);
for (i=0; i<how_many; i++)
values[i] = va_arg(ap, int);
@@ -1717,7 +1775,7 @@
ffi.cdef("char sum3chars(char *);")
lib = ffi.verify("""
char sum3chars(char *f) {
- return f[0] + f[1] + f[2];
+ return (char)(f[0] + f[1] + f[2]);
}
""")
assert lib.sum3chars((b'\x10', b'\x20', b'\x30')) == b'\x60'
@@ -1817,6 +1875,7 @@
long tf_bl(signed char x, long c);
unsigned long tf_bL(signed char x, unsigned long c);
long long tf_bq(signed char x, long long c);
+ unsigned long long tf_bQ(signed char x, unsigned long long c);
float tf_bf(signed char x, float c);
double tf_bd(signed char x, double c);
long double tf_bD(signed char x, long double c);
@@ -1834,20 +1893,35 @@
double dvalue;
long double Dvalue;
- #define S(letter) xvalue = x; letter##value = c; return rvalue;
+ typedef signed char b_t;
+ typedef unsigned char B_t;
+ typedef short h_t;
+ typedef unsigned short H_t;
+ typedef int i_t;
+ typedef unsigned int I_t;
+ typedef long l_t;
+ typedef unsigned long L_t;
+ typedef long long q_t;
+ typedef unsigned long long Q_t;
+ typedef float f_t;
+ typedef double d_t;
+ typedef long double D_t;
+ #define S(letter) xvalue = (int)x; letter##value = (letter##_t)c;
+ #define R(letter) return (letter##_t)rvalue;
- signed char tf_bb(signed char x, signed char c) { S(i) }
- unsigned char tf_bB(signed char x, unsigned char c) { S(i) }
- short tf_bh(signed char x, short c) { S(i) }
- unsigned short tf_bH(signed char x, unsigned short c) { S(i) }
- int tf_bi(signed char x, int c) { S(i) }
- unsigned int tf_bI(signed char x, unsigned int c) { S(i) }
- long tf_bl(signed char x, long c) { S(i) }
- unsigned long tf_bL(signed char x, unsigned long c) { S(i) }
- long long tf_bq(signed char x, long long c) { S(i) }
- float tf_bf(signed char x, float c) { S(f) }
- double tf_bd(signed char x, double c) { S(d) }
- long double tf_bD(signed char x, long double c) { S(D) }
+ signed char tf_bb(signed char x, signed char c) { S(i) R(b) }
+ unsigned char tf_bB(signed char x, unsigned char c) { S(i) R(B) }
+ short tf_bh(signed char x, short c) { S(i) R(h) }
+ unsigned short tf_bH(signed char x, unsigned short c) { S(i) R(H) }
+ int tf_bi(signed char x, int c) { S(i) R(i) }
+ unsigned int tf_bI(signed char x, unsigned int c) { S(i) R(I) }
+ long tf_bl(signed char x, long c) { S(i) R(l) }
+ unsigned long tf_bL(signed char x, unsigned long c) { S(i) R(L) }
+ long long tf_bq(signed char x, long long c) { S(i) R(q) }
+ unsigned long long tf_bQ(signed char x, unsigned long long c) { S(i) R(Q) }
+ float tf_bf(signed char x, float c) { S(f) R(f) }
+ double tf_bd(signed char x, double c) { S(d) R(d) }
+ long double tf_bD(signed char x, long double c) { S(D) R(D) }
""")
lib.rvalue = 0x7182838485868788
for kind, cname in [('b', 'signed char'),
@@ -1859,6 +1933,7 @@
('l', 'long'),
('L', 'unsigned long'),
('q', 'long long'),
+ ('Q', 'unsigned long long'),
('f', 'float'),
('d', 'double'),
('D', 'long double')]:
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit