Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit