Author: Armin Rigo <[email protected]>
Branch:
Changeset: r77662:b4e3775e779c
Date: 2015-05-28 19:26 +0200
http://bitbucket.org/pypy/pypy/changeset/b4e3775e779c/
Log: pypy/tool/import_cffi: import revision 020ef1915196
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -11,7 +11,7 @@
class GlobalExpr:
- def __init__(self, name, address, type_op, size=0, check_value=None):
+ def __init__(self, name, address, type_op, size=0, check_value=0):
self.name = name
self.address = address
self.type_op = type_op
@@ -23,11 +23,6 @@
self.name, self.address, self.type_op.as_c_expr(), self.size)
def as_python_expr(self):
- if not isinstance(self.check_value, int_type):
- raise ffiplatform.VerificationError(
- "ffi.dlopen() will not be able to figure out the value of "
- "constant %r (only integer constants are supported, and only "
- "if their value are specified in the cdef)" % (self.name,))
return "b'%s%s',%d" % (self.type_op.as_python_bytes(), self.name,
self.check_value)
@@ -747,7 +742,7 @@
meth_kind = OP_CPYTHON_BLTN_V # 'METH_VARARGS'
self._lsts["global"].append(
GlobalExpr(name, '_cffi_f_%s' % name,
- CffiOp(meth_kind, type_index), check_value=0,
+ CffiOp(meth_kind, type_index),
size='_cffi_d_%s' % name))
# ----------
@@ -971,7 +966,7 @@
def _generate_cpy_constant_collecttype(self, tp, name):
is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
- if not is_int:
+ if not is_int or self.target_is_python:
self._do_collect_type(tp)
def _generate_cpy_constant_decl(self, tp, name):
@@ -979,9 +974,14 @@
self._generate_cpy_const(is_int, name, tp)
def _generate_cpy_constant_ctx(self, tp, name):
- if isinstance(tp, model.PrimitiveType) and tp.is_integer_type():
+ if (not self.target_is_python and
+ isinstance(tp, model.PrimitiveType) and tp.is_integer_type()):
type_op = CffiOp(OP_CONSTANT_INT, -1)
else:
+ if not tp.sizeof_enabled():
+ raise ffiplatform.VerificationError(
+ "constant '%s' is of type '%s', whose size is not known"
+ % (name, tp._get_c_name()))
type_index = self._typesdict[tp]
type_op = CffiOp(OP_CONSTANT, type_index)
self._lsts["global"].append(
@@ -1034,6 +1034,10 @@
def _generate_cpy_macro_ctx(self, tp, name):
if tp == '...':
+ if self.target_is_python:
+ raise ffiplatform.VerificationError(
+ "cannot use the syntax '...' in '#define %s ...' when "
+ "using the ABI mode" % (name,))
check_value = None
else:
check_value = tp # an integer
@@ -1066,7 +1070,7 @@
else:
size = 0
self._lsts["global"].append(
- GlobalExpr(name, '&%s' % name, type_op, size, 0))
+ GlobalExpr(name, '&%s' % name, type_op, size))
# ----------
# emitting the opcodes for individual types
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py
@@ -20,27 +20,20 @@
)
"""
-def test_invalid_global_constant():
+def test_global_constant():
ffi = FFI()
- ffi.cdef("static const int BB;")
- target = udir.join('test_invalid_global_constants.py')
- e = py.test.raises(VerificationError, make_py_source, ffi,
- 'test_invalid_global_constants', str(target))
- assert str(e.value) == (
- "ffi.dlopen() will not be able to figure out "
- "the value of constant 'BB' (only integer constants are "
- "supported, and only if their value are specified in the cdef)")
+ ffi.cdef("static const long BB; static const float BF = 12;")
+ target = udir.join('test_valid_global_constant.py')
+ make_py_source(ffi, 'test_valid_global_constant', str(target))
+ assert target.read() == r"""# auto-generated file
+import _cffi_backend
-def test_invalid_global_constant_2():
- ffi = FFI()
- ffi.cdef("static const float BB = 12;")
- target = udir.join('test_invalid_global_constants_2.py')
- e = py.test.raises(VerificationError, make_py_source, ffi,
- 'test_invalid_global_constants_2', str(target))
- assert str(e.value) == (
- "ffi.dlopen() will not be able to figure out "
- "the value of constant 'BB' (only integer constants are "
- "supported, and only if their value are specified in the cdef)")
+ffi = _cffi_backend.FFI('test_valid_global_constant',
+ _version = 0x2601,
+ _types = b'\x00\x00\x0D\x01\x00\x00\x09\x01',
+ _globals = (b'\x00\x00\x01\x1DBB',0,b'\x00\x00\x00\x1DBF',0),
+)
+"""
def test_invalid_global_constant_3():
ffi = FFI()
@@ -54,10 +47,8 @@
target = udir.join('test_invalid_dotdotdot_in_macro.py')
e = py.test.raises(VerificationError, make_py_source, ffi,
'test_invalid_dotdotdot_in_macro', str(target))
- assert str(e.value) == (
- "ffi.dlopen() will not be able to figure out "
- "the value of constant 'FOO' (only integer constants are "
- "supported, and only if their value are specified in the cdef)")
+ assert str(e.value) == ("macro FOO: cannot use the syntax '...' in "
+ "'#define FOO ...' when using the ABI mode")
def test_typename():
ffi = FFI()
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py
@@ -15,6 +15,8 @@
int add42(int x) { return x + 42; }
int add43(int x, ...) { return x; }
int globalvar42 = 1234;
+ const int globalconst42 = 4321;
+ const char *const globalconsthello = "hello";
struct foo_s;
typedef struct bar_s { int x; signed char a[]; } bar_t;
enum foo_e { AA, BB, CC };
@@ -29,7 +31,8 @@
ext = ffiplatform.get_extension(
str(c_file),
'_test_re_python',
- export_symbols=['add42', 'add43', 'globalvar42']
+ export_symbols=['add42', 'add43', 'globalvar42',
+ 'globalconst42', 'globalconsthello']
)
outputfilename = ffiplatform.compile(str(tmpdir), ext)
mod.extmod = outputfilename
@@ -44,6 +47,8 @@
int add42(int);
int add43(int, ...);
int globalvar42;
+ const int globalconst42;
+ const char *const globalconsthello = "hello";
int no_such_function(int);
int no_such_globalvar;
struct foo_s;
@@ -153,6 +158,18 @@
p[0] -= 1
assert lib.globalvar42 == 1238
+def test_global_const_int():
+ from re_python_pysrc import ffi
+ lib = ffi.dlopen(extmod)
+ assert lib.globalconst42 == 4321
+ py.test.raises(AttributeError, ffi.addressof, lib, 'globalconst42')
+
+def test_global_const_nonint():
+ from re_python_pysrc import ffi
+ lib = ffi.dlopen(extmod)
+ assert ffi.string(lib.globalconsthello, 8) == "hello"
+ py.test.raises(AttributeError, ffi.addressof, lib, 'globalconsthello')
+
def test_rtld_constants():
from re_python_pysrc import ffi
ffi.RTLD_NOW # check that we have the attributes
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
@@ -824,3 +824,87 @@
assert addr(0xABC05) == 47
assert isinstance(addr, ffi.CData)
assert ffi.typeof(addr) == ffi.typeof("long(*)(long)")
+
+def test_issue198():
+ ffi = FFI()
+ ffi.cdef("""
+ typedef struct{...;} opaque_t;
+ const opaque_t CONSTANT;
+ int toint(opaque_t);
+ """)
+ lib = verify(ffi, 'test_issue198', """
+ typedef int opaque_t;
+ #define CONSTANT ((opaque_t)42)
+ static int toint(opaque_t o) { return o; }
+ """)
+ def random_stuff():
+ pass
+ assert lib.toint(lib.CONSTANT) == 42
+ random_stuff()
+ assert lib.toint(lib.CONSTANT) == 42
+
+def test_constant_is_not_a_compiler_constant():
+ ffi = FFI()
+ ffi.cdef("static const float almost_forty_two;")
+ lib = verify(ffi, 'test_constant_is_not_a_compiler_constant', """
+ static float f(void) { return 42.25; }
+ #define almost_forty_two (f())
+ """)
+ assert lib.almost_forty_two == 42.25
+
+def test_constant_of_unknown_size():
+ ffi = FFI()
+ ffi.cdef("""
+ typedef ... opaque_t;
+ const opaque_t CONSTANT;
+ """)
+ e = py.test.raises(VerificationError, verify, ffi,
+ 'test_constant_of_unknown_size', "stuff")
+ assert str(e.value) == ("constant CONSTANT: constant 'CONSTANT' is of "
+ "type 'opaque_t', whose size is not known")
+
+def test_variable_of_unknown_size():
+ ffi = FFI()
+ ffi.cdef("""
+ typedef ... opaque_t;
+ opaque_t globvar;
+ """)
+ lib = verify(ffi, 'test_constant_of_unknown_size', """
+ typedef char opaque_t[6];
+ opaque_t globvar = "hello";
+ """)
+ # can't read or write it at all
+ e = py.test.raises(TypeError, getattr, lib, 'globvar')
+ assert str(e.value) == "cdata 'opaque_t' is opaque"
+ e = py.test.raises(TypeError, setattr, lib, 'globvar', [])
+ assert str(e.value) == "'opaque_t' is opaque"
+ # but we can get its address
+ p = ffi.addressof(lib, 'globvar')
+ assert ffi.typeof(p) == ffi.typeof('opaque_t *')
+ assert ffi.string(ffi.cast("char *", p), 8) == "hello"
+
+def test_constant_of_value_unknown_to_the_compiler():
+ extra_c_source = udir.join(
+ 'extra_test_constant_of_value_unknown_to_the_compiler.c')
+ extra_c_source.write('const int external_foo = 42;\n')
+ ffi = FFI()
+ ffi.cdef("const int external_foo;")
+ lib = verify(ffi, 'test_constant_of_value_unknown_to_the_compiler', """
+ extern const int external_foo;
+ """, sources=[str(extra_c_source)])
+ assert lib.external_foo == 42
+
+def test_call_with_incomplete_structs():
+ ffi = FFI()
+ ffi.cdef("typedef struct {...;} foo_t; "
+ "foo_t myglob; "
+ "foo_t increment(foo_t s); "
+ "double getx(foo_t s);")
+ lib = verify(ffi, 'test_call_with_incomplete_structs', """
+ typedef double foo_t;
+ double myglob = 42.5;
+ double getx(double x) { return x; }
+ double increment(double x) { return x + 1; }
+ """)
+ assert lib.getx(lib.myglob) == 42.5
+ assert lib.getx(lib.increment(lib.myglob)) == 43.5
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit