Author: Armin Rigo <ar...@tunes.org> 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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit