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

Reply via email to