Author: Armin Rigo <[email protected]> Branch: Changeset: r78419:3968d9b3c744 Date: 2015-07-03 16:51 +0200 http://bitbucket.org/pypy/pypy/changeset/3968d9b3c744/
Log: Update to cffi/5fd800db658c diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO --- a/lib_pypy/cffi.egg-info/PKG-INFO +++ b/lib_pypy/cffi.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: cffi -Version: 1.1.2 +Version: 1.2.0 Summary: Foreign Function Interface for Python calling C code. Home-page: http://cffi.readthedocs.org Author: Armin Rigo, Maciej Fijalkowski diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py --- a/lib_pypy/cffi/__init__.py +++ b/lib_pypy/cffi/__init__.py @@ -4,8 +4,8 @@ from .api import FFI, CDefError, FFIError from .ffiplatform import VerificationError, VerificationMissing -__version__ = "1.1.2" -__version_info__ = (1, 1, 2) +__version__ = "1.2.0" +__version_info__ = (1, 2, 0) # The verifier module file names are based on the CRC32 of a string that # contains the following version number. It may be older than __version__ diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -428,6 +428,8 @@ raise TypeError("ffi.include() expects an argument that is also of" " type cffi.FFI, not %r" % ( type(ffi_to_include).__name__,)) + if ffi_to_include is self: + raise ValueError("self.include(self)") with ffi_to_include._lock: with self._lock: self._parser.include(ffi_to_include._parser) diff --git a/lib_pypy/cffi/cffi_opcode.py b/lib_pypy/cffi/cffi_opcode.py --- a/lib_pypy/cffi/cffi_opcode.py +++ b/lib_pypy/cffi/cffi_opcode.py @@ -53,6 +53,7 @@ OP_GLOBAL_VAR = 33 OP_DLOPEN_FUNC = 35 OP_DLOPEN_CONST = 37 +OP_GLOBAL_VAR_F = 39 PRIM_VOID = 0 PRIM_BOOL = 1 diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py --- a/lib_pypy/cffi/cparser.py +++ b/lib_pypy/cffi/cparser.py @@ -633,6 +633,8 @@ def include(self, other): for name, tp in other._declarations.items(): + if name.startswith('anonymous $enum_$'): + continue # fix for test_anonymous_enum_include kind = name.split(' ', 1)[0] if kind in ('struct', 'union', 'enum', 'anonymous'): self._declare(name, tp, included=True) diff --git a/lib_pypy/cffi/model.py b/lib_pypy/cffi/model.py --- a/lib_pypy/cffi/model.py +++ b/lib_pypy/cffi/model.py @@ -35,9 +35,6 @@ def is_integer_type(self): return False - def sizeof_enabled(self): - return False - def get_cached_btype(self, ffi, finishlist, can_delay=False): try: BType = ffi._cached_btypes[self] @@ -80,8 +77,7 @@ class BasePrimitiveType(BaseType): - def sizeof_enabled(self): - return True + pass class PrimitiveType(BasePrimitiveType): @@ -205,9 +201,6 @@ class FunctionPtrType(BaseFunctionType): _base_pattern = '(*&)(%s)' - def sizeof_enabled(self): - return True - def build_backend_type(self, ffi, finishlist): result = self.result.get_cached_btype(ffi, finishlist) args = [] @@ -233,9 +226,6 @@ extra = self._base_pattern self.c_name_with_marker = totype.c_name_with_marker.replace('&', extra) - def sizeof_enabled(self): - return True - def build_backend_type(self, ffi, finishlist): BItem = self.totype.get_cached_btype(ffi, finishlist, can_delay=True) return global_cache(self, ffi, 'new_pointer_type', BItem) @@ -276,9 +266,6 @@ self.c_name_with_marker = ( self.item.c_name_with_marker.replace('&', brackets)) - def sizeof_enabled(self): - return self.item.sizeof_enabled() and self.length is not None - def resolve_length(self, newlength): return ArrayType(self.item, newlength) @@ -433,9 +420,6 @@ from . import ffiplatform raise ffiplatform.VerificationMissing(self._get_c_name()) - def sizeof_enabled(self): - return self.fldtypes is not None - def build_backend_type(self, ffi, finishlist): self.check_not_partial() finishlist.append(self) @@ -464,9 +448,6 @@ self.baseinttype = baseinttype self.build_c_name_with_marker() - def sizeof_enabled(self): - return True # not strictly true, but external enums are obscure - def force_the_name(self, forcename): StructOrUnionOrEnum.force_the_name(self, forcename) if self.forcename is None: diff --git a/lib_pypy/cffi/parse_c_type.h b/lib_pypy/cffi/parse_c_type.h --- a/lib_pypy/cffi/parse_c_type.h +++ b/lib_pypy/cffi/parse_c_type.h @@ -26,6 +26,7 @@ #define _CFFI_OP_GLOBAL_VAR 33 #define _CFFI_OP_DLOPEN_FUNC 35 #define _CFFI_OP_DLOPEN_CONST 37 +#define _CFFI_OP_GLOBAL_VAR_F 39 #define _CFFI_PRIM_VOID 0 #define _CFFI_PRIM_BOOL 1 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 @@ -981,10 +981,6 @@ if not self.target_is_python 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())) if self.target_is_python: const_kind = OP_DLOPEN_CONST else: @@ -1069,18 +1065,36 @@ self._do_collect_type(self._global_type(tp, name)) def _generate_cpy_variable_decl(self, tp, name): - pass + prnt = self._prnt + tp = self._global_type(tp, name) + if isinstance(tp, model.ArrayType) and tp.length is None: + tp = tp.item + ampersand = '' + else: + ampersand = '&' + # This code assumes that casts from "tp *" to "void *" is a + # no-op, i.e. a function that returns a "tp *" can be called + # as if it returned a "void *". This should be generally true + # on any modern machine. The only exception to that rule (on + # uncommon architectures, and as far as I can tell) might be + # if 'tp' were a function type, but that is not possible here. + # (If 'tp' is a function _pointer_ type, then casts from "fn_t + # **" to "void *" are again no-ops, as far as I can tell.) + prnt('static ' + tp.get_c_name('*_cffi_var_%s(void)' % (name,))) + prnt('{') + prnt(' return %s(%s);' % (ampersand, name)) + prnt('}') + prnt() def _generate_cpy_variable_ctx(self, tp, name): tp = self._global_type(tp, name) type_index = self._typesdict[tp] - type_op = CffiOp(OP_GLOBAL_VAR, type_index) - if tp.sizeof_enabled(): - size = "sizeof(%s)" % (name,) + if self.target_is_python: + op = OP_GLOBAL_VAR else: - size = 0 + op = OP_GLOBAL_VAR_F self._lsts["global"].append( - GlobalExpr(name, '&%s' % name, type_op, size)) + GlobalExpr(name, '_cffi_var_%s' % name, CffiOp(op, type_index))) # ---------- # emitting the opcodes for individual types diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py --- a/pypy/module/_cffi_backend/__init__.py +++ b/pypy/module/_cffi_backend/__init__.py @@ -2,7 +2,7 @@ from pypy.interpreter.mixedmodule import MixedModule from rpython.rlib import rdynload -VERSION = "1.1.2" +VERSION = "1.2.0" class Module(MixedModule): diff --git a/pypy/module/_cffi_backend/cdlopen.py b/pypy/module/_cffi_backend/cdlopen.py --- a/pypy/module/_cffi_backend/cdlopen.py +++ b/pypy/module/_cffi_backend/cdlopen.py @@ -36,7 +36,10 @@ self.libname) try: cdata = dlsym(self.libhandle, name) + found = bool(cdata) except KeyError: + found = False + if not found: raise oefmt(self.ffi.w_FFIError, "symbol '%s' not found in library '%s'", name, self.libname) diff --git a/pypy/module/_cffi_backend/cffi_opcode.py b/pypy/module/_cffi_backend/cffi_opcode.py --- a/pypy/module/_cffi_backend/cffi_opcode.py +++ b/pypy/module/_cffi_backend/cffi_opcode.py @@ -53,6 +53,7 @@ OP_GLOBAL_VAR = 33 OP_DLOPEN_FUNC = 35 OP_DLOPEN_CONST = 37 +OP_GLOBAL_VAR_F = 39 PRIM_VOID = 0 PRIM_BOOL = 1 diff --git a/pypy/module/_cffi_backend/cglob.py b/pypy/module/_cffi_backend/cglob.py --- a/pypy/module/_cffi_backend/cglob.py +++ b/pypy/module/_cffi_backend/cglob.py @@ -2,23 +2,38 @@ from pypy.interpreter.typedef import TypeDef from pypy.module._cffi_backend.cdataobj import W_CData from pypy.module._cffi_backend import newtype +from rpython.rlib.objectmodel import we_are_translated +from rpython.rtyper.lltypesystem import lltype, rffi + +FNPTR = rffi.CCallback([], rffi.VOIDP) class W_GlobSupport(W_Root): - def __init__(self, space, w_ctype, ptr): + _immutable_fields_ = ['w_ctype', 'ptr', 'fetch_addr'] + + def __init__(self, space, w_ctype, ptr=lltype.nullptr(rffi.CCHARP.TO), + fetch_addr=lltype.nullptr(rffi.VOIDP.TO)): self.space = space self.w_ctype = w_ctype self.ptr = ptr + self.fetch_addr = rffi.cast(FNPTR, fetch_addr) + + def fetch_global_var_addr(self): + if self.ptr: + return self.ptr + result = self.fetch_addr() + return rffi.cast(rffi.CCHARP, result) def read_global_var(self): - return self.w_ctype.convert_to_object(self.ptr) + return self.w_ctype.convert_to_object(self.fetch_global_var_addr()) def write_global_var(self, w_newvalue): - self.w_ctype.convert_from_object(self.ptr, w_newvalue) + self.w_ctype.convert_from_object(self.fetch_global_var_addr(), + w_newvalue) def address(self): w_ctypeptr = newtype.new_pointer_type(self.space, self.w_ctype) - return W_CData(self.space, self.ptr, w_ctypeptr) + return W_CData(self.space, self.fetch_global_var_addr(), w_ctypeptr) W_GlobSupport.typedef = TypeDef("FFIGlobSupport") W_GlobSupport.typedef.acceptable_as_base_class = False diff --git a/pypy/module/_cffi_backend/lib_obj.py b/pypy/module/_cffi_backend/lib_obj.py --- a/pypy/module/_cffi_backend/lib_obj.py +++ b/pypy/module/_cffi_backend/lib_obj.py @@ -102,6 +102,8 @@ # elif op == cffi_opcode.OP_GLOBAL_VAR: # A global variable of the exact type specified here + # (nowadays, only used by the ABI mode or backend + # compatibility; see OP_GLOBAL_F for the API mode w_ct = realize_c_type.realize_c_type( self.ffi, self.ctx.c_types, getarg(g.c_type_op)) g_size = rffi.cast(lltype.Signed, g.c_size_or_direct_fn) @@ -113,7 +115,13 @@ ptr = rffi.cast(rffi.CCHARP, g.c_address) if not ptr: # for dlopen() style ptr = self.cdlopen_fetch(attr) - w_result = cglob.W_GlobSupport(space, w_ct, ptr) + w_result = cglob.W_GlobSupport(space, w_ct, ptr=ptr) + # + elif op == cffi_opcode.OP_GLOBAL_VAR_F: + w_ct = realize_c_type.realize_c_type( + self.ffi, self.ctx.c_types, getarg(g.c_type_op)) + w_result = cglob.W_GlobSupport(space, w_ct, + fetch_addr=g.c_address) # elif (op == cffi_opcode.OP_CONSTANT_INT or op == cffi_opcode.OP_ENUM): @@ -131,6 +139,9 @@ realize_c_type.FUNCPTR_FETCH_CHARP, g.c_address) if w_ct.size <= 0: + raise oefmt(self.ffi.w_FFIError, + "constant '%s' is of type '%s', " + "whose size is not known", attr, w_ct.name) raise oefmt(space.w_SystemError, "constant has no known size") if not fetch_funcptr: # for dlopen() style @@ -172,7 +183,7 @@ w_value = self._build_attr(attr) if w_value is None: if is_getattr and attr == '__all__': - return self.dir1(ignore_type=cffi_opcode.OP_GLOBAL_VAR) + return self.dir1(ignore_global_vars=True) if is_getattr and attr == '__dict__': return self.full_dict_copy() if is_getattr and attr == '__name__': @@ -206,14 +217,18 @@ def descr_dir(self): return self.dir1() - def dir1(self, ignore_type=-1): + def dir1(self, ignore_global_vars=False): space = self.space total = rffi.getintfield(self.ctx, 'c_num_globals') g = self.ctx.c_globals names_w = [] for i in range(total): - if getop(g[i].c_type_op) != ignore_type: - names_w.append(space.wrap(rffi.charp2str(g[i].c_name))) + if ignore_global_vars: + op = getop(g[i].c_type_op) + if (op == cffi_opcode.OP_GLOBAL_VAR or + op == cffi_opcode.OP_GLOBAL_VAR_F): + continue + names_w.append(space.wrap(rffi.charp2str(g[i].c_name))) return space.newlist(names_w) def full_dict_copy(self): diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -3343,4 +3343,4 @@ def test_version(): # this test is here mostly for PyPy - assert __version__ == "1.1.2" + assert __version__ == "1.2.0" diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py b/pypy/module/_cffi_backend/test/test_recompiler.py --- a/pypy/module/_cffi_backend/test/test_recompiler.py +++ b/pypy/module/_cffi_backend/test/test_recompiler.py @@ -16,8 +16,8 @@ from cffi import ffiplatform except ImportError: py.test.skip("system cffi module not found or older than 1.0.0") - if cffi.__version_info__ < (1, 0, 4): - py.test.skip("system cffi module needs to be at least 1.0.4") + if cffi.__version_info__ < (1, 2, 0): + py.test.skip("system cffi module needs to be at least 1.2.0") space.appexec([], """(): import _cffi_backend # force it to be initialized """) @@ -500,28 +500,33 @@ "int foo(int x) { return x + 32; }") assert lib.foo(10) == 42 - def test_bad_size_of_global_1(self): - ffi, lib = self.prepare( - "short glob;", - "test_bad_size_of_global_1", - "long glob;") - raises(ffi.error, getattr, lib, "glob") - - def test_bad_size_of_global_2(self): - ffi, lib = self.prepare( - "int glob[10];", - "test_bad_size_of_global_2", - "int glob[9];") - e = raises(ffi.error, getattr, lib, "glob") - assert str(e.value) == ("global variable 'glob' should be 40 bytes " - "according to the cdef, but is actually 36") - - def test_unspecified_size_of_global(self): + def test_unspecified_size_of_global_1(self): ffi, lib = self.prepare( "int glob[];", - "test_unspecified_size_of_global", + "test_unspecified_size_of_global_1", "int glob[10];") - lib.glob # does not crash + assert ffi.typeof(lib.glob) == ffi.typeof("int *") + + def test_unspecified_size_of_global_2(self): + ffi, lib = self.prepare( + "int glob[][5];", + "test_unspecified_size_of_global_2", + "int glob[10][5];") + assert ffi.typeof(lib.glob) == ffi.typeof("int(*)[5]") + + def test_unspecified_size_of_global_3(self): + ffi, lib = self.prepare( + "int glob[][...];", + "test_unspecified_size_of_global_3", + "int glob[10][5];") + assert ffi.typeof(lib.glob) == ffi.typeof("int(*)[5]") + + def test_unspecified_size_of_global_4(self): + ffi, lib = self.prepare( + "int glob[...][...];", + "test_unspecified_size_of_global_4", + "int glob[10][5];") + assert ffi.typeof(lib.glob) == ffi.typeof("int[10][5]") def test_include_1(self): ffi1, lib1 = self.prepare( @@ -869,11 +874,22 @@ """) assert lib.almost_forty_two == 42.25 + def test_constant_of_unknown_size(self): + ffi, lib = self.prepare( + "typedef ... opaque_t;" + "const opaque_t CONSTANT;", + 'test_constant_of_unknown_size', + "typedef int opaque_t;" + "const int CONSTANT = 42;") + e = raises(ffi.error, getattr, lib, 'CONSTANT') + assert str(e.value) == ("constant 'CONSTANT' is of " + "type 'opaque_t', whose size is not known") + def test_variable_of_unknown_size(self): ffi, lib = self.prepare(""" typedef ... opaque_t; opaque_t globvar; - """, 'test_constant_of_unknown_size', """ + """, 'test_variable_of_unknown_size', """ typedef char opaque_t[6]; opaque_t globvar = "hello"; """) @@ -1012,3 +1028,32 @@ assert hasattr(lib, '__dict__') assert lib.__all__ == ['MYFOO', 'mybar'] # but not 'myvar' assert lib.__name__ == repr(lib) + + def test_macro_var_callback(self): + ffi, lib = self.prepare( + "int my_value; int *(*get_my_value)(void);", + 'test_macro_var_callback', + "int *(*get_my_value)(void);\n" + "#define my_value (*get_my_value())") + # + values = ffi.new("int[50]") + def it(): + for i in range(50): + yield i + it = it() + # + @ffi.callback("int *(*)(void)") + def get_my_value(): + return values + it.next() + lib.get_my_value = get_my_value + # + values[0] = 41 + assert lib.my_value == 41 # [0] + p = ffi.addressof(lib, 'my_value') # [1] + assert p == values + 1 + assert p[-1] == 41 + assert p[+1] == 0 + lib.my_value = 42 # [2] + assert values[2] == 42 + assert p[-1] == 41 + assert p[+1] == 42 diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py @@ -1771,3 +1771,18 @@ py.test.raises(TypeError, ffi.new, "struct foo_s *") ffi.cdef("struct foo_s { int x; };") ffi.new("struct foo_s *") + + def test_ffi_self_include(self): + ffi = FFI(backend=self.Backend()) + py.test.raises(ValueError, ffi.include, ffi) + + def test_anonymous_enum_include(self): + ffi1 = FFI() + ffi1.cdef("enum { EE1 };") + ffi = FFI() + ffi.include(ffi1) + ffi.cdef("enum { EE2, EE3 };") + lib = ffi.dlopen(None) + assert lib.EE1 == 0 + assert lib.EE2 == 0 + assert lib.EE3 == 1 diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_new_ffi_1.py @@ -1715,6 +1715,6 @@ assert myvar == -5 # but can't be changed, so not very useful py.test.raises(ImportError, "from _test_import_from_lib.lib import bar") d = {} - exec "from _test_import_from_lib.lib import *" in d + exec("from _test_import_from_lib.lib import *", d) assert (set(key for key in d if not key.startswith('_')) == set(['myfunc', 'MYFOO'])) 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 @@ -1,4 +1,5 @@ # Generated by pypy/tool/import_cffi.py + import sys, os, py from cffi import FFI, VerificationError from cffi import recompiler @@ -511,22 +512,38 @@ def test_bad_size_of_global_1(): ffi = FFI() ffi.cdef("short glob;") - lib = verify(ffi, "test_bad_size_of_global_1", "long glob;") - py.test.raises(ffi.error, "lib.glob") + py.test.raises(VerificationError, verify, ffi, + "test_bad_size_of_global_1", "long glob;") def test_bad_size_of_global_2(): ffi = FFI() ffi.cdef("int glob[10];") - lib = verify(ffi, "test_bad_size_of_global_2", "int glob[9];") - e = py.test.raises(ffi.error, "lib.glob") - assert str(e.value) == ("global variable 'glob' should be 40 bytes " - "according to the cdef, but is actually 36") + py.test.raises(VerificationError, verify, ffi, + "test_bad_size_of_global_2", "int glob[9];") -def test_unspecified_size_of_global(): +def test_unspecified_size_of_global_1(): ffi = FFI() ffi.cdef("int glob[];") - lib = verify(ffi, "test_unspecified_size_of_global", "int glob[10];") - lib.glob # does not crash + lib = verify(ffi, "test_unspecified_size_of_global_1", "int glob[10];") + assert ffi.typeof(lib.glob) == ffi.typeof("int *") + +def test_unspecified_size_of_global_2(): + ffi = FFI() + ffi.cdef("int glob[][5];") + lib = verify(ffi, "test_unspecified_size_of_global_2", "int glob[10][5];") + assert ffi.typeof(lib.glob) == ffi.typeof("int(*)[5]") + +def test_unspecified_size_of_global_3(): + ffi = FFI() + ffi.cdef("int glob[][...];") + lib = verify(ffi, "test_unspecified_size_of_global_3", "int glob[10][5];") + assert ffi.typeof(lib.glob) == ffi.typeof("int(*)[5]") + +def test_unspecified_size_of_global_4(): + ffi = FFI() + ffi.cdef("int glob[...][...];") + lib = verify(ffi, "test_unspecified_size_of_global_4", "int glob[10][5];") + assert ffi.typeof(lib.glob) == ffi.typeof("int[10][5]") def test_include_1(): ffi1 = FFI() @@ -839,6 +856,22 @@ assert isinstance(addr, ffi.CData) assert ffi.typeof(addr) == ffi.typeof("long(*)(long)") +def test_address_of_function_with_struct(): + ffi = FFI() + ffi.cdef("struct foo_s { int x; }; long myfunc(struct foo_s);") + lib = verify(ffi, "test_addressof_function_with_struct", """ + struct foo_s { int x; }; + char myfunc(struct foo_s input) { return (char)(input.x + 42); } + """) + s = ffi.new("struct foo_s *", [5])[0] + assert lib.myfunc(s) == 47 + assert not isinstance(lib.myfunc, ffi.CData) + assert ffi.typeof(lib.myfunc) == ffi.typeof("long(*)(struct foo_s)") + addr = ffi.addressof(lib, 'myfunc') + assert addr(s) == 47 + assert isinstance(addr, ffi.CData) + assert ffi.typeof(addr) == ffi.typeof("long(*)(struct foo_s)") + def test_issue198(): ffi = FFI() ffi.cdef(""" @@ -872,9 +905,11 @@ 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 " + lib = verify(ffi, 'test_constant_of_unknown_size', + "typedef int opaque_t;" + "const int CONSTANT = 42;") + e = py.test.raises(ffi.error, getattr, lib, 'CONSTANT') + assert str(e.value) == ("constant 'CONSTANT' is of " "type 'opaque_t', whose size is not known") def test_variable_of_unknown_size(): @@ -883,7 +918,7 @@ typedef ... opaque_t; opaque_t globvar; """) - lib = verify(ffi, 'test_constant_of_unknown_size', """ + lib = verify(ffi, 'test_variable_of_unknown_size', """ typedef char opaque_t[6]; opaque_t globvar = "hello"; """) @@ -1064,3 +1099,33 @@ assert MYFOO == 42 assert hasattr(lib, '__dict__') assert lib.__all__ == ['MYFOO', 'mybar'] # but not 'myvar' + assert lib.__name__ == repr(lib) + +def test_macro_var_callback(): + ffi = FFI() + ffi.cdef("int my_value; int *(*get_my_value)(void);") + lib = verify(ffi, 'test_macro_var_callback', + "int *(*get_my_value)(void);\n" + "#define my_value (*get_my_value())") + # + values = ffi.new("int[50]") + def it(): + for i in range(50): + yield i + it = it() + # + @ffi.callback("int *(*)(void)") + def get_my_value(): + return values + it.next() + lib.get_my_value = get_my_value + # + values[0] = 41 + assert lib.my_value == 41 # [0] + p = ffi.addressof(lib, 'my_value') # [1] + assert p == values + 1 + assert p[-1] == 41 + assert p[+1] == 0 + lib.my_value = 42 # [2] + assert values[2] == 42 + assert p[-1] == 41 + assert p[+1] == 42 diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_verify1.py @@ -2231,3 +2231,39 @@ # ffi.cdef("typedef int... foo_t;") py.test.raises(VerificationError, ffi.verify, "typedef float foo_t;") + +def test_windows_dllimport_data(): + if sys.platform != 'win32': + py.test.skip("Windows only") + from pypy.module.test_lib_pypy.cffi_tests.udir import udir + tmpfile = udir.join('dllimport_data.c') + tmpfile.write('int my_value = 42;\n') + ffi = FFI() + ffi.cdef("int my_value;") + lib = ffi.verify("extern __declspec(dllimport) int my_value;", + sources = [str(tmpfile)]) + assert lib.my_value == 42 + +def test_macro_var(): + ffi = FFI() + ffi.cdef("int myarray[50], my_value;") + lib = ffi.verify(""" + int myarray[50]; + int *get_my_value(void) { + static int index = 0; + return &myarray[index++]; + } + #define my_value (*get_my_value()) + """) + assert lib.my_value == 0 # [0] + lib.my_value = 42 # [1] + assert lib.myarray[1] == 42 + assert lib.my_value == 0 # [2] + lib.myarray[3] = 63 + assert lib.my_value == 63 # [3] + p = ffi.addressof(lib, 'my_value') # [4] + assert p[-1] == 63 + assert p[0] == 0 + assert p == lib.myarray + 4 + p[1] = 82 + assert lib.my_value == 82 # [5] diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py @@ -68,6 +68,8 @@ name += '.SO' if name.startswith('pycparser') and name.endswith('.egg'): continue # no clue why this shows up sometimes and not others + if name == '.eggs': + continue # seems new in 3.5, ignore it assert name in content, "found unexpected file %r" % ( os.path.join(curdir, name),) value = content.pop(name) _______________________________________________ pypy-commit mailing list [email protected] https://mail.python.org/mailman/listinfo/pypy-commit
