Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r75270:3db26c31b597 Date: 2015-01-09 11:45 +0100 http://bitbucket.org/pypy/pypy/changeset/3db26c31b597/
Log: Run pypy/tool/import_cffi.py 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 @@ -6,3 +6,8 @@ __version__ = "0.8.6" __version_info__ = (0, 8, 6) + +# 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__ +# if nothing is clearly incompatible. +__version_verifier_modules__ = "0.8.6" 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 @@ -69,6 +69,7 @@ self._function_caches = [] self._libraries = [] self._cdefsources = [] + self._windows_unicode = None if hasattr(backend, 'set_ffi'): backend.set_ffi(self) for name in backend.__dict__: @@ -77,6 +78,7 @@ # with self._lock: self.BVoidP = self._get_cached_btype(model.voidp_type) + self.BCharA = self._get_cached_btype(model.char_array_type) if isinstance(backend, types.ModuleType): # _cffi_backend: attach these constants to the class if not hasattr(FFI, 'NULL'): @@ -191,11 +193,12 @@ def offsetof(self, cdecl, fieldname): """Return the offset of the named field inside the given - structure, which must be given as a C type name. + structure, which must be given as a C type name. The field + may be 'x.y.z' in case of nested structures. """ if isinstance(cdecl, basestring): cdecl = self._typeof(cdecl) - return self._backend.typeoffsetof(cdecl, fieldname)[1] + return self._typeoffsetof(cdecl, fieldname)[1] def new(self, cdecl, init=None): """Allocate an instance according to the specified C type and @@ -264,6 +267,16 @@ """ return self._backend.buffer(cdata, size) + def from_buffer(self, python_buffer): + """Return a <cdata 'char[]'> that points to the data of the + given Python object, which must support the buffer interface. + Note that this is not meant to be used on the built-in types str, + unicode, or bytearray (you can build 'char[]' arrays explicitly) + but only on objects containing large quantities of raw data + in some other format, like 'array.array' or numpy arrays. + """ + return self._backend.from_buffer(self.BCharA, python_buffer) + def callback(self, cdecl, python_callable=None, error=None): """Return a callback object or a decorator making such a callback object. 'cdecl' must name a C function pointer type. @@ -335,9 +348,23 @@ which requires binary compatibility in the signatures. """ from .verifier import Verifier, _caller_dir_pycache + # + # If set_unicode(True) was called, insert the UNICODE and + # _UNICODE macro declarations + if self._windows_unicode: + self._apply_windows_unicode(kwargs) + # + # Set the tmpdir here, and not in Verifier.__init__: it picks + # up the caller's directory, which we want to be the caller of + # ffi.verify(), as opposed to the caller of Veritier(). tmpdir = tmpdir or _caller_dir_pycache() + # + # Make a Verifier() and use it to load the library. self.verifier = Verifier(self, source, tmpdir, **kwargs) lib = self.verifier.load_library() + # + # Save the loaded library for keep-alive purposes, even + # if the caller doesn't keep it alive itself (it should). self._libraries.append(lib) return lib @@ -359,12 +386,22 @@ def addressof(self, cdata, field=None): """Return the address of a <cdata 'struct-or-union'>. If 'field' is specified, return the address of this field. + The field may be 'x.y.z' in case of nested structures. """ ctype = self._backend.typeof(cdata) - ctype, offset = self._backend.typeoffsetof(ctype, field) + ctype, offset = self._typeoffsetof(ctype, field) ctypeptr = self._pointer_to(ctype) return self._backend.rawaddressof(ctypeptr, cdata, offset) + def _typeoffsetof(self, ctype, field): + if field is not None and '.' in field: + offset = 0 + for field1 in field.split('.'): + ctype, offset1 = self._backend.typeoffsetof(ctype, field1) + offset += offset1 + return ctype, offset + return self._backend.typeoffsetof(ctype, field) + def include(self, ffi_to_include): """Includes the typedefs, structs, unions and enums defined in another FFI instance. Usage is similar to a #include in C, @@ -387,6 +424,44 @@ def from_handle(self, x): return self._backend.from_handle(x) + def set_unicode(self, enabled_flag): + """Windows: if 'enabled_flag' is True, enable the UNICODE and + _UNICODE defines in C, and declare the types like TCHAR and LPTCSTR + to be (pointers to) wchar_t. If 'enabled_flag' is False, + declare these types to be (pointers to) plain 8-bit characters. + This is mostly for backward compatibility; you usually want True. + """ + if self._windows_unicode is not None: + raise ValueError("set_unicode() can only be called once") + enabled_flag = bool(enabled_flag) + if enabled_flag: + self.cdef("typedef wchar_t TBYTE;" + "typedef wchar_t TCHAR;" + "typedef const wchar_t *LPCTSTR;" + "typedef const wchar_t *PCTSTR;" + "typedef wchar_t *LPTSTR;" + "typedef wchar_t *PTSTR;" + "typedef TBYTE *PTBYTE;" + "typedef TCHAR *PTCHAR;") + else: + self.cdef("typedef char TBYTE;" + "typedef char TCHAR;" + "typedef const char *LPCTSTR;" + "typedef const char *PCTSTR;" + "typedef char *LPTSTR;" + "typedef char *PTSTR;" + "typedef TBYTE *PTBYTE;" + "typedef TCHAR *PTCHAR;") + self._windows_unicode = enabled_flag + + def _apply_windows_unicode(self, kwds): + defmacros = kwds.get('define_macros', ()) + if not isinstance(defmacros, (list, tuple)): + raise TypeError("'define_macros' must be a list or tuple") + defmacros = list(defmacros) + [('UNICODE', '1'), + ('_UNICODE', '1')] + kwds['define_macros'] = defmacros + def _load_backend_lib(backend, name, flags): if name is None: diff --git a/lib_pypy/cffi/commontypes.py b/lib_pypy/cffi/commontypes.py --- a/lib_pypy/cffi/commontypes.py +++ b/lib_pypy/cffi/commontypes.py @@ -29,6 +29,9 @@ result = model.PointerType(resolve_common_type(result[:-2])) elif result in model.PrimitiveType.ALL_PRIMITIVE_TYPES: result = model.PrimitiveType(result) + elif result == 'set-unicode-needed': + raise api.FFIError("The Windows type %r is only available after " + "you call ffi.set_unicode()" % (commontype,)) else: if commontype == result: raise api.FFIError("Unsupported type: %r. Please file a bug " @@ -86,8 +89,6 @@ "ULONGLONG": "unsigned long long", "WCHAR": "wchar_t", "SHORT": "short", - "TBYTE": "WCHAR", - "TCHAR": "WCHAR", "UCHAR": "unsigned char", "UINT": "unsigned int", "UINT8": "unsigned char", @@ -157,14 +158,12 @@ "LPCVOID": model.const_voidp_type, "LPCWSTR": "const WCHAR *", - "LPCTSTR": "LPCWSTR", "LPDWORD": "DWORD *", "LPHANDLE": "HANDLE *", "LPINT": "int *", "LPLONG": "long *", "LPSTR": "CHAR *", "LPWSTR": "WCHAR *", - "LPTSTR": "LPWSTR", "LPVOID": model.voidp_type, "LPWORD": "WORD *", "LRESULT": "LONG_PTR", @@ -173,7 +172,6 @@ "PBYTE": "BYTE *", "PCHAR": "CHAR *", "PCSTR": "const CHAR *", - "PCTSTR": "LPCWSTR", "PCWSTR": "const WCHAR *", "PDWORD": "DWORD *", "PDWORDLONG": "DWORDLONG *", @@ -200,9 +198,6 @@ "PSIZE_T": "SIZE_T *", "PSSIZE_T": "SSIZE_T *", "PSTR": "CHAR *", - "PTBYTE": "TBYTE *", - "PTCHAR": "TCHAR *", - "PTSTR": "LPWSTR", "PUCHAR": "UCHAR *", "PUHALF_PTR": "UHALF_PTR *", "PUINT": "UINT *", @@ -240,6 +235,15 @@ "USN": "LONGLONG", "VOID": model.void_type, "WPARAM": "UINT_PTR", + + "TBYTE": "set-unicode-needed", + "TCHAR": "set-unicode-needed", + "LPCTSTR": "set-unicode-needed", + "PCTSTR": "set-unicode-needed", + "LPTSTR": "set-unicode-needed", + "PTSTR": "set-unicode-needed", + "PTBYTE": "set-unicode-needed", + "PTCHAR;": "set-unicode-needed", }) return result 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 @@ -1,4 +1,3 @@ - from . import api, model from .commontypes import COMMON_TYPES, resolve_common_type try: @@ -209,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 @@ -460,6 +461,8 @@ elif kind == 'union': tp = model.UnionType(explicit_name, None, None, None) elif kind == 'enum': + if explicit_name == '__dotdotdot__': + raise CDefError("Enums cannot be declared with ...") tp = self._build_enum_type(explicit_name, type.values) else: raise AssertionError("kind = %r" % (kind,)) @@ -532,9 +535,24 @@ def _parse_constant(self, exprnode, partial_length_ok=False): # for now, limited to expressions that are an immediate number - # or negative number + # or positive/negative number if isinstance(exprnode, pycparser.c_ast.Constant): - return int(exprnode.value, 0) + s = exprnode.value + if s.startswith('0'): + if s.startswith('0x') or s.startswith('0X'): + return int(s, 16) + return int(s, 8) + elif '1' <= s[0] <= '9': + return int(s, 10) + elif s[0] == "'" and s[-1] == "'" and ( + len(s) == 3 or (len(s) == 4 and s[1] == "\\")): + return ord(s[-2]) + else: + raise api.CDefError("invalid constant %r" % (s,)) + # + if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and + exprnode.op == '+'): + return self._parse_constant(exprnode.expr) # if (isinstance(exprnode, pycparser.c_ast.UnaryOp) and exprnode.op == '-'): diff --git a/lib_pypy/cffi/ffiplatform.py b/lib_pypy/cffi/ffiplatform.py --- a/lib_pypy/cffi/ffiplatform.py +++ b/lib_pypy/cffi/ffiplatform.py @@ -11,6 +11,9 @@ """ +LIST_OF_FILE_NAMES = ['sources', 'include_dirs', 'library_dirs', + 'extra_objects', 'depends'] + def get_extension(srcfilename, modname, sources=(), **kwds): from distutils.core import Extension allsources = [srcfilename] 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 @@ -235,6 +235,8 @@ BPtrItem = PointerType(self.item).get_cached_btype(ffi, finishlist) return global_cache(self, ffi, 'new_array_type', BPtrItem, self.length) +char_array_type = ArrayType(PrimitiveType('char'), None) + class StructOrUnionOrEnum(BaseTypeByIdentity): _attrs_ = ('name',) @@ -478,7 +480,7 @@ try: res = getattr(ffi._backend, funcname)(*args) except NotImplementedError as e: - raise NotImplementedError("%r: %s" % (srctype, e)) + raise NotImplementedError("%s: %r: %s" % (funcname, srctype, e)) # note that setdefault() on WeakValueDictionary is not atomic # and contains a rare bug (http://bugs.python.org/issue19542); # we have to use a lock and do it ourselves diff --git a/lib_pypy/cffi/vengine_cpy.py b/lib_pypy/cffi/vengine_cpy.py --- a/lib_pypy/cffi/vengine_cpy.py +++ b/lib_pypy/cffi/vengine_cpy.py @@ -65,7 +65,7 @@ # The following two 'chained_list_constants' items contains # the head of these two chained lists, as a string that gives the # call to do, if any. - self._chained_list_constants = ['0', '0'] + self._chained_list_constants = ['((void)lib,0)', '((void)lib,0)'] # prnt = self._prnt # first paste some standard set of lines that are mostly '#define' @@ -138,15 +138,22 @@ prnt() prnt('#endif') - def load_library(self): + def load_library(self, flags=None): # XXX review all usages of 'self' here! # import it as a new extension module + if hasattr(sys, "getdlopenflags"): + previous_flags = sys.getdlopenflags() try: + if hasattr(sys, "setdlopenflags") and flags is not None: + sys.setdlopenflags(flags) module = imp.load_dynamic(self.verifier.get_module_name(), self.verifier.modulefilename) except ImportError as e: error = "importing %r: %s" % (self.verifier.modulefilename, e) raise ffiplatform.VerificationError(error) + finally: + if hasattr(sys, "setdlopenflags"): + sys.setdlopenflags(previous_flags) # # call loading_cpy_struct() to get the struct layout inferred by # the C compiler @@ -228,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): @@ -267,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)) @@ -336,7 +344,7 @@ prnt = self._prnt numargs = len(tp.args) if numargs == 0: - argname = 'no_arg' + argname = 'noarg' elif numargs == 1: argname = 'arg0' else: @@ -386,6 +394,9 @@ prnt(' Py_END_ALLOW_THREADS') prnt() # + prnt(' (void)self; /* unused */') + if numargs == 0: + prnt(' (void)noarg; /* unused */') if result_code: prnt(' return %s;' % self._convert_expr_from_c(tp.result, 'result', 'result type')) @@ -452,6 +463,7 @@ prnt('static void %s(%s *p)' % (checkfuncname, cname)) prnt('{') prnt(' /* only to generate compile-time warnings or errors */') + prnt(' (void)p;') for fname, ftype, fbitsize in tp.enumfields(): if (isinstance(ftype, model.PrimitiveType) and ftype.is_integer_type()) or fbitsize >= 0: @@ -482,6 +494,8 @@ prnt(' sizeof(((%s *)0)->%s),' % (cname, fname)) prnt(' -1') prnt(' };') + prnt(' (void)self; /* unused */') + prnt(' (void)noarg; /* unused */') prnt(' return _cffi_get_struct_layout(nums);') prnt(' /* the next line is not executed, but compiled */') prnt(' %s(0);' % (checkfuncname,)) @@ -653,14 +667,14 @@ prnt('static int %s(PyObject *lib)' % funcname) prnt('{') for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): - if enumvalue < 0: - prnt(' if ((%s) >= 0 || (long)(%s) != %dL) {' % ( + if enumvalue <= 0: + prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % ( enumerator, enumerator, enumvalue)) else: - prnt(' if ((%s) < 0 || (unsigned long)(%s) != %dUL) {' % ( + prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % ( enumerator, enumerator, enumvalue)) prnt(' char buf[64];') - prnt(' if ((%s) < 0)' % enumerator) + prnt(' if ((%s) <= 0)' % enumerator) prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % enumerator) prnt(' else') prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' % @@ -783,6 +797,24 @@ typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; + typedef __int8 int_least8_t; + typedef __int16 int_least16_t; + typedef __int32 int_least32_t; + typedef __int64 int_least64_t; + typedef unsigned __int8 uint_least8_t; + typedef unsigned __int16 uint_least16_t; + typedef unsigned __int32 uint_least32_t; + typedef unsigned __int64 uint_least64_t; + typedef __int8 int_fast8_t; + typedef __int16 int_fast16_t; + typedef __int32 int_fast32_t; + typedef __int64 int_fast64_t; + typedef unsigned __int8 uint_fast8_t; + typedef unsigned __int16 uint_fast16_t; + typedef unsigned __int32 uint_fast32_t; + typedef unsigned __int64 uint_fast64_t; + typedef __int64 intmax_t; + typedef unsigned __int64 uintmax_t; # else # include <stdint.h> # endif @@ -828,12 +860,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) \ @@ -844,7 +879,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]) @@ -907,6 +942,7 @@ { PyObject *library; int was_alive = (_cffi_types != NULL); + (void)self; /* unused */ if (!PyArg_ParseTuple(args, "OOO", &_cffi_types, &_cffi_VerificationError, &library)) return NULL; diff --git a/lib_pypy/cffi/vengine_gen.py b/lib_pypy/cffi/vengine_gen.py --- a/lib_pypy/cffi/vengine_gen.py +++ b/lib_pypy/cffi/vengine_gen.py @@ -58,12 +58,12 @@ modname = self.verifier.get_module_name() prnt("void %s%s(void) { }\n" % (prefix, modname)) - def load_library(self): + def load_library(self, flags=0): # import it with the CFFI backend backend = self.ffi._backend # needs to make a path that contains '/', on Posix filename = os.path.join(os.curdir, self.verifier.modulefilename) - module = backend.load_library(filename) + module = backend.load_library(filename, flags) # # call loading_gen_struct() to get the struct layout inferred by # the C compiler @@ -235,6 +235,7 @@ prnt('static void %s(%s *p)' % (checkfuncname, cname)) prnt('{') prnt(' /* only to generate compile-time warnings or errors */') + prnt(' (void)p;') for fname, ftype, fbitsize in tp.enumfields(): if (isinstance(ftype, model.PrimitiveType) and ftype.is_integer_type()) or fbitsize >= 0: @@ -427,14 +428,14 @@ prnt('int %s(char *out_error)' % funcname) prnt('{') for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues): - if enumvalue < 0: - prnt(' if ((%s) >= 0 || (long)(%s) != %dL) {' % ( + if enumvalue <= 0: + prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % ( enumerator, enumerator, enumvalue)) else: - prnt(' if ((%s) < 0 || (unsigned long)(%s) != %dUL) {' % ( + prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % ( enumerator, enumerator, enumvalue)) prnt(' char buf[64];') - prnt(' if ((%s) < 0)' % enumerator) + prnt(' if ((%s) <= 0)' % enumerator) prnt(' sprintf(buf, "%%ld", (long)(%s));' % enumerator) prnt(' else') prnt(' sprintf(buf, "%%lu", (unsigned long)(%s));' % @@ -565,6 +566,24 @@ typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; + typedef __int8 int_least8_t; + typedef __int16 int_least16_t; + typedef __int32 int_least32_t; + typedef __int64 int_least64_t; + typedef unsigned __int8 uint_least8_t; + typedef unsigned __int16 uint_least16_t; + typedef unsigned __int32 uint_least32_t; + typedef unsigned __int64 uint_least64_t; + typedef __int8 int_fast8_t; + typedef __int16 int_fast16_t; + typedef __int32 int_fast32_t; + typedef __int64 int_fast64_t; + typedef unsigned __int8 uint_fast8_t; + typedef unsigned __int16 uint_fast16_t; + typedef unsigned __int32 uint_fast32_t; + typedef unsigned __int64 uint_fast64_t; + typedef __int64 intmax_t; + typedef unsigned __int64 uintmax_t; # else # include <stdint.h> # endif diff --git a/lib_pypy/cffi/verifier.py b/lib_pypy/cffi/verifier.py --- a/lib_pypy/cffi/verifier.py +++ b/lib_pypy/cffi/verifier.py @@ -1,12 +1,23 @@ -import sys, os, binascii, imp, shutil -from . import __version__ +import sys, os, binascii, shutil +from . import __version_verifier_modules__ from . import ffiplatform +if sys.version_info >= (3, 3): + import importlib.machinery + def _extension_suffixes(): + return importlib.machinery.EXTENSION_SUFFIXES[:] +else: + import imp + def _extension_suffixes(): + return [suffix for suffix, _, type in imp.get_suffixes() + if type == imp.C_EXTENSION] + class Verifier(object): def __init__(self, ffi, preamble, tmpdir=None, modulename=None, - ext_package=None, tag='', force_generic_engine=False, **kwds): + ext_package=None, tag='', force_generic_engine=False, + source_extension='.c', flags=None, relative_to=None, **kwds): self.ffi = ffi self.preamble = preamble if not modulename: @@ -14,14 +25,15 @@ vengine_class = _locate_engine_class(ffi, force_generic_engine) self._vengine = vengine_class(self) self._vengine.patch_extension_kwds(kwds) - self.kwds = kwds + self.flags = flags + self.kwds = self.make_relative_to(kwds, relative_to) # if modulename: if tag: raise TypeError("can't specify both 'modulename' and 'tag'") else: - key = '\x00'.join([sys.version[:3], __version__, preamble, - flattened_kwds] + + key = '\x00'.join([sys.version[:3], __version_verifier_modules__, + preamble, flattened_kwds] + ffi._cdefsources) if sys.version_info >= (3,): key = key.encode('utf-8') @@ -33,7 +45,7 @@ k1, k2) suffix = _get_so_suffixes()[0] self.tmpdir = 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 @@ -97,6 +109,20 @@ def generates_python_module(self): return self._vengine._gen_python_module + def make_relative_to(self, kwds, relative_to): + if relative_to and os.path.dirname(relative_to): + dirname = os.path.dirname(relative_to) + kwds = kwds.copy() + for key in ffiplatform.LIST_OF_FILE_NAMES: + if key in kwds: + lst = kwds[key] + if not isinstance(lst, (list, tuple)): + raise TypeError("keyword '%s' should be a list or tuple" + % (key,)) + lst = [os.path.join(dirname, fn) for fn in lst] + kwds[key] = lst + return kwds + # ---------- def _locate_module(self): @@ -148,7 +174,10 @@ def _load_library(self): assert self._has_module - return self._vengine.load_library() + if self.flags is not None: + return self._vengine.load_library(self.flags) + else: + return self._vengine.load_library() # ____________________________________________________________ @@ -181,6 +210,9 @@ def _caller_dir_pycache(): if _TMPDIR: return _TMPDIR + result = os.environ.get('CFFI_TMPDIR') + if result: + return result filename = sys._getframe(2).f_code.co_filename return os.path.abspath(os.path.join(os.path.dirname(filename), '__pycache__')) @@ -222,11 +254,7 @@ pass def _get_so_suffixes(): - suffixes = [] - for suffix, mode, type in imp.get_suffixes(): - if type == imp.C_EXTENSION: - suffixes.append(suffix) - + suffixes = _extension_suffixes() if not suffixes: # bah, no C_EXTENSION available. Occurs on pypy without cpyext if sys.platform == 'win32': diff --git a/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py b/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py --- a/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py +++ b/pypy/module/test_lib_pypy/cffi_tests/backend_tests.py @@ -2,7 +2,7 @@ import py import platform import sys, ctypes -from cffi import FFI, CDefError +from cffi import FFI, CDefError, FFIError from pypy.module.test_lib_pypy.cffi_tests.support import * SIZE_OF_INT = ctypes.sizeof(ctypes.c_int) @@ -917,6 +917,16 @@ assert int(invalid_value) == 2 assert ffi.string(invalid_value) == "2" + def test_enum_char_hex_oct(self): + ffi = FFI(backend=self.Backend()) + ffi.cdef(r"enum foo{A='!', B='\'', C=0x10, D=010, E=- 0x10, F=-010};") + assert ffi.string(ffi.cast("enum foo", ord('!'))) == "A" + assert ffi.string(ffi.cast("enum foo", ord("'"))) == "B" + assert ffi.string(ffi.cast("enum foo", 16)) == "C" + assert ffi.string(ffi.cast("enum foo", 8)) == "D" + assert ffi.string(ffi.cast("enum foo", -16)) == "E" + assert ffi.string(ffi.cast("enum foo", -8)) == "F" + def test_array_of_struct(self): ffi = FFI(backend=self.Backend()) ffi.cdef("struct foo { int a, b; };") @@ -950,6 +960,15 @@ assert ffi.offsetof("struct foo", "b") == 4 assert ffi.offsetof("struct foo", "c") == 8 + def test_offsetof_nested(self): + ffi = FFI(backend=self.Backend()) + ffi.cdef("struct foo { int a, b, c; };" + "struct bar { struct foo d, e; };") + assert ffi.offsetof("struct bar", "e") == 12 + assert ffi.offsetof("struct bar", "e.a") == 12 + assert ffi.offsetof("struct bar", "e.b") == 16 + assert ffi.offsetof("struct bar", "e.c") == 20 + def test_alignof(self): ffi = FFI(backend=self.Backend()) ffi.cdef("struct foo { char a; short b; char c; };") @@ -1496,6 +1515,16 @@ assert a == ffi.addressof(p, 'y') assert a != ffi.addressof(p, 'x') + def test_addressof_field_nested(self): + ffi = FFI(backend=self.Backend()) + ffi.cdef("struct foo_s { int x, y; };" + "struct bar_s { struct foo_s a, b; };") + p = ffi.new("struct bar_s *") + a = ffi.addressof(p[0], 'b.y') + assert int(ffi.cast("uintptr_t", a)) == ( + int(ffi.cast("uintptr_t", p)) + + ffi.sizeof("struct foo_s") + ffi.sizeof("int")) + def test_addressof_anonymous_struct(self): ffi = FFI() ffi.cdef("typedef struct { int x; } foo_t;") @@ -1565,6 +1594,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/pypy/module/test_lib_pypy/cffi_tests/test_cdata.py b/pypy/module/test_lib_pypy/cffi_tests/test_cdata.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_cdata.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_cdata.py @@ -20,6 +20,8 @@ return FakeType("void") def new_pointer_type(self, x): return FakeType('ptr-to-%r' % (x,)) + def new_array_type(self, x, y): + return FakeType('array-from-%r-len-%r' % (x, y)) def cast(self, x, y): return 'casted!' def _get_types(self): diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_ffi_backend.py b/pypy/module/test_lib_pypy/cffi_tests/test_ffi_backend.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_ffi_backend.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_ffi_backend.py @@ -20,8 +20,8 @@ ffi.cdef("struct foo_s { int a,b,c,d,e; int x:1; };") e = py.test.raises(NotImplementedError, ffi.callback, "struct foo_s foo(void)", lambda: 42) - assert str(e.value) == ("<struct foo_s(*)(void)>: " - "cannot pass as argument or return value a struct with bit fields") + assert str(e.value) == ("struct foo_s(*)(): " + "callback with unsupported argument or return type or with '...'") def test_inspecttype(self): ffi = FFI(backend=self.Backend()) @@ -123,7 +123,7 @@ self.check("int a:2; short b:15; char c:2; char y;", 5, 4, 8) self.check("int a:2; char b:1; char c:1; char y;", 1, 4, 4) - @pytest.mark.skipif("platform.machine().startswith('arm')") + @pytest.mark.skipif("platform.machine().startswith(('arm', 'aarch64'))") def test_bitfield_anonymous_no_align(self): L = FFI().alignof("long long") self.check("char y; int :1;", 0, 1, 2) @@ -136,7 +136,8 @@ self.check("char x; long long z:57; char y;", L + 8, L, L + 8 + L) self.check("char x; long long :57; char y;", L + 8, 1, L + 9) - @pytest.mark.skipif("not platform.machine().startswith('arm')") + @pytest.mark.skipif( + "not platform.machine().startswith(('arm', 'aarch64'))") def test_bitfield_anonymous_align_arm(self): L = FFI().alignof("long long") self.check("char y; int :1;", 0, 4, 4) @@ -149,7 +150,7 @@ self.check("char x; long long z:57; char y;", L + 8, L, L + 8 + L) self.check("char x; long long :57; char y;", L + 8, L, L + 8 + L) - @pytest.mark.skipif("platform.machine().startswith('arm')") + @pytest.mark.skipif("platform.machine().startswith(('arm', 'aarch64'))") def test_bitfield_zero(self): L = FFI().alignof("long long") self.check("char y; int :0;", 0, 1, 4) @@ -160,7 +161,8 @@ self.check("char x; int :0; short b:1; char y;", 5, 2, 6) self.check("int a:1; int :0; int b:1; char y;", 5, 4, 8) - @pytest.mark.skipif("not platform.machine().startswith('arm')") + @pytest.mark.skipif( + "not platform.machine().startswith(('arm', 'aarch64'))") def test_bitfield_zero_arm(self): L = FFI().alignof("long long") self.check("char y; int :0;", 0, 4, 4) @@ -212,3 +214,12 @@ code, message = ffi.getwinerror(-1) assert code == 2 assert message == "The system cannot find the file specified" + + def test_from_buffer(self): + import array + ffi = FFI() + a = array.array('H', [10000, 20000, 30000]) + c = ffi.from_buffer(a) + assert ffi.typeof(c) is ffi.typeof("char[]") + ffi.cast("unsigned short *", c)[1] += 500 + assert list(a) == [10000, 20500, 30000] diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_parsing.py b/pypy/module/test_lib_pypy/cffi_tests/test_parsing.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_parsing.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_parsing.py @@ -289,3 +289,14 @@ decl = ast.children()[0][1] node = decl.type assert p._is_constant_globalvar(node) == expected_output + +def test_enum(): + ffi = FFI() + ffi.cdef(""" + enum Enum { POS = +1, TWO = 2, NIL = 0, NEG = -1}; + """) + C = ffi.dlopen(None) + assert C.POS == 1 + assert C.TWO == 2 + assert C.NIL == 0 + assert C.NEG == -1 diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_verify.py b/pypy/module/test_lib_pypy/cffi_tests/test_verify.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_verify.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_verify.py @@ -1,7 +1,7 @@ # Generated by pypy/tool/import_cffi.py import py, re import sys, os, math, weakref -from cffi import FFI, VerificationError, VerificationMissing, model +from cffi import FFI, VerificationError, VerificationMissing, model, FFIError from pypy.module.test_lib_pypy.cffi_tests.support import * @@ -15,12 +15,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', '-Wall', '-Wextra', '-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', '-Wall', '-Wextra', '-Wconversion'] class FFI(FFI): def verify(self, *args, **kwds): @@ -90,11 +91,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 @@ -113,14 +151,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 @@ -209,8 +254,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(' ', '_')) @@ -316,7 +361,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") @@ -386,7 +431,7 @@ ffi = FFI() ffi.cdef("typedef struct foo_s foo_t; int bar(foo_t *);") lib = ffi.verify("typedef struct foo_s foo_t;\n" - "int bar(foo_t *f) { return 42; }\n") + "int bar(foo_t *f) { (void)f; return 42; }\n") assert lib.bar(ffi.NULL) == 42 def test_ffi_full_struct(): @@ -897,7 +942,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) @@ -992,7 +1037,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]) @@ -1009,7 +1054,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; """) @@ -1068,7 +1113,7 @@ def test_array_as_argument(): ffi = FFI() ffi.cdef(""" - int strlen(char string[]); + size_t strlen(char string[]); """) ffi.verify("#include <string.h>") @@ -1080,7 +1125,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") @@ -1093,7 +1138,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 @@ -1128,6 +1173,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(""" @@ -1136,7 +1194,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 @@ -1292,7 +1350,7 @@ """) def test_tmpdir(): - import tempfile, os, shutil + import tempfile, os from pypy.module.test_lib_pypy.cffi_tests.udir import udir tmpdir = tempfile.mkdtemp(dir=str(udir)) ffi = FFI() @@ -1301,6 +1359,20 @@ assert os.listdir(tmpdir) assert lib.foo(100) == 142 +def test_relative_to(): + import tempfile, os + from pypy.module.test_lib_pypy.cffi_tests.udir import udir + tmpdir = tempfile.mkdtemp(dir=str(udir)) + ffi = FFI() + ffi.cdef("int foo(int);") + f = open(os.path.join(tmpdir, 'foo.h'), 'w') + print >> f, "int foo(int a) { return a + 42; }" + f.close() + lib = ffi.verify('#include "foo.h"', + include_dirs=['.'], + relative_to=os.path.join(tmpdir, 'x')) + assert lib.foo(100) == 142 + def test_bug1(): ffi = FFI() ffi.cdef(""" @@ -1677,7 +1749,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); @@ -1718,7 +1790,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' @@ -1753,7 +1825,7 @@ def test_typeof_function(): ffi = FFI() ffi.cdef("int foo(int, char);") - lib = ffi.verify("int foo(int x, char y) { return 42; }") + lib = ffi.verify("int foo(int x, char y) { (void)x; (void)y; return 42; }") ctype = ffi.typeof(lib.foo) assert len(ctype.args) == 2 assert ctype.result == ffi.typeof("int") @@ -1818,6 +1890,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); @@ -1835,20 +1908,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'), @@ -1860,6 +1948,7 @@ ('l', 'long'), ('L', 'unsigned long'), ('q', 'long long'), + ('Q', 'unsigned long long'), ('f', 'float'), ('d', 'double'), ('D', 'long double')]: @@ -1963,3 +2052,77 @@ n = (1 << 29) + i lib.SetLastError(n) assert ffi.getwinerror()[0] == n + +def test_verify_dlopen_flags(): + ffi1 = FFI() + ffi1.cdef("int foo;") + + lib1 = ffi1.verify("int foo;", flags=ffi1.RTLD_GLOBAL | ffi1.RTLD_LAZY) + lib2 = get_second_lib() + + lib1.foo = 42 + + assert lib2.foo == 42 + +def get_second_lib(): + # Hack, using modulename makes the test fail + ffi2 = FFI() + ffi2.cdef("int foo;") + lib2 = ffi2.verify("int foo;", flags=ffi2.RTLD_GLOBAL | ffi2.RTLD_LAZY) + return lib2 + +def test_consider_not_implemented_function_type(): + ffi = FFI() + ffi.cdef("typedef union { int a; float b; } Data;" + "typedef struct { int a:2; } MyStr;" + "typedef void (*foofunc_t)(Data);" + "typedef MyStr (*barfunc_t)(void);") + fooptr = ffi.cast("foofunc_t", 123) + barptr = ffi.cast("barfunc_t", 123) + # assert did not crash so far + e = py.test.raises(NotImplementedError, fooptr, ffi.new("Data *")) + assert str(e.value) == ( + "ctype 'Data' not supported as argument or return value") + e = py.test.raises(NotImplementedError, barptr) + assert str(e.value) == ( + "ctype 'MyStr' not supported as argument or return value " + "(it is a struct with bit fields)") + +def test_verify_extra_arguments(): + ffi = FFI() + ffi.cdef("#define ABA ...") + lib = ffi.verify("", define_macros=[('ABA', '42')]) + assert lib.ABA == 42 + +def test_implicit_unicode_on_windows(): + if sys.platform != 'win32': + py.test.skip("win32-only test") + ffi = FFI() + e = py.test.raises(FFIError, ffi.cdef, "int foo(LPTSTR);") + assert str(e.value) == ("The Windows type 'LPTSTR' is only available after" + " you call ffi.set_unicode()") + for with_unicode in [True, False]: + ffi = FFI() + ffi.set_unicode(with_unicode) + ffi.cdef(""" + DWORD GetModuleFileName(HMODULE hModule, LPTSTR lpFilename, + DWORD nSize); + """) + lib = ffi.verify(""" + #include <windows.h> + """, libraries=['Kernel32']) + outbuf = ffi.new("TCHAR[]", 200) + n = lib.GetModuleFileName(ffi.NULL, outbuf, 500) + assert 0 < n < 500 + for i in range(n): + print repr(outbuf[i]) + assert ord(outbuf[i]) != 0 + assert ord(outbuf[n]) == 0 + assert ord(outbuf[0]) < 128 # should be a letter, or '\' + +def test_use_local_dir(): + ffi = FFI() + lib = ffi.verify("", modulename="test_use_local_dir") + this_dir = os.path.dirname(__file__) + pycache_files = os.listdir(os.path.join(this_dir, '__pycache__')) + assert any('test_use_local_dir' in s for s in pycache_files) diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_zdistutils.py b/pypy/module/test_lib_pypy/cffi_tests/test_zdistutils.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_zdistutils.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_zdistutils.py @@ -18,7 +18,7 @@ def teardown_class(self): if udir.isdir(): - udir.remove() + udir.remove(ignore_errors=True) def test_locate_engine_class(self): cls = _locate_engine_class(FFI(), self.generic) diff --git a/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py b/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py --- a/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py +++ b/pypy/module/test_lib_pypy/cffi_tests/test_zintegration.py @@ -76,7 +76,7 @@ class TestZIntegration(object): def teardown_class(self): if udir.isdir(): - udir.remove() + udir.remove(ignore_errors=True) def test_infrastructure(self): run_setup_and_program('infrastructure', ''' _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit