update Linux_x86_64
This commit is contained in:
parent
93422b0274
commit
e7ebbedd38
336 changed files with 34353 additions and 21020 deletions
|
|
@ -4,5 +4,10 @@ __all__ = ['FFI', 'VerificationError', 'VerificationMissing', 'CDefError',
|
|||
from .api import FFI, CDefError, FFIError
|
||||
from .ffiplatform import VerificationError, VerificationMissing
|
||||
|
||||
__version__ = "0.8.6"
|
||||
__version_info__ = (0, 8, 6)
|
||||
__version__ = "1.3.0"
|
||||
__version_info__ = (1, 3, 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__
|
||||
# if nothing is clearly incompatible.
|
||||
__version_verifier_modules__ = "0.8.6"
|
||||
|
|
|
|||
229
Linux_x86_64/lib/python3.4/site-packages/cffi/_cffi_include.h
Normal file
229
Linux_x86_64/lib/python3.4/site-packages/cffi/_cffi_include.h
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
#define _CFFI_
|
||||
#include <Python.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include <stddef.h>
|
||||
#include "parse_c_type.h"
|
||||
|
||||
/* this block of #ifs should be kept exactly identical between
|
||||
c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py
|
||||
and cffi/_cffi_include.h */
|
||||
#if defined(_MSC_VER)
|
||||
# include <malloc.h> /* for alloca() */
|
||||
# if _MSC_VER < 1600 /* MSVC < 2010 */
|
||||
typedef __int8 int8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
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
|
||||
# if _MSC_VER < 1800 /* MSVC < 2013 */
|
||||
typedef unsigned char _Bool;
|
||||
# endif
|
||||
#else
|
||||
# include <stdint.h>
|
||||
# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux)
|
||||
# include <alloca.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define _CFFI_UNUSED_FN __attribute__((unused))
|
||||
#else
|
||||
# define _CFFI_UNUSED_FN /* nothing */
|
||||
#endif
|
||||
|
||||
/********** CPython-specific section **********/
|
||||
#ifndef PYPY_VERSION
|
||||
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
# define PyInt_FromLong PyLong_FromLong
|
||||
#endif
|
||||
|
||||
#define _cffi_from_c_double PyFloat_FromDouble
|
||||
#define _cffi_from_c_float PyFloat_FromDouble
|
||||
#define _cffi_from_c_long PyInt_FromLong
|
||||
#define _cffi_from_c_ulong PyLong_FromUnsignedLong
|
||||
#define _cffi_from_c_longlong PyLong_FromLongLong
|
||||
#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong
|
||||
|
||||
#define _cffi_to_c_double PyFloat_AsDouble
|
||||
#define _cffi_to_c_float PyFloat_AsDouble
|
||||
|
||||
#define _cffi_from_c_int(x, type) \
|
||||
(((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) \
|
||||
((type)( \
|
||||
sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \
|
||||
: (type)_cffi_to_c_i8(o)) : \
|
||||
sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \
|
||||
: (type)_cffi_to_c_i16(o)) : \
|
||||
sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \
|
||||
: (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), (type)0)))
|
||||
|
||||
#define _cffi_to_c_i8 \
|
||||
((int(*)(PyObject *))_cffi_exports[1])
|
||||
#define _cffi_to_c_u8 \
|
||||
((int(*)(PyObject *))_cffi_exports[2])
|
||||
#define _cffi_to_c_i16 \
|
||||
((int(*)(PyObject *))_cffi_exports[3])
|
||||
#define _cffi_to_c_u16 \
|
||||
((int(*)(PyObject *))_cffi_exports[4])
|
||||
#define _cffi_to_c_i32 \
|
||||
((int(*)(PyObject *))_cffi_exports[5])
|
||||
#define _cffi_to_c_u32 \
|
||||
((unsigned int(*)(PyObject *))_cffi_exports[6])
|
||||
#define _cffi_to_c_i64 \
|
||||
((long long(*)(PyObject *))_cffi_exports[7])
|
||||
#define _cffi_to_c_u64 \
|
||||
((unsigned long long(*)(PyObject *))_cffi_exports[8])
|
||||
#define _cffi_to_c_char \
|
||||
((int(*)(PyObject *))_cffi_exports[9])
|
||||
#define _cffi_from_c_pointer \
|
||||
((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10])
|
||||
#define _cffi_to_c_pointer \
|
||||
((char *(*)(PyObject *, CTypeDescrObject *))_cffi_exports[11])
|
||||
#define _cffi_get_struct_layout \
|
||||
not used any more
|
||||
#define _cffi_restore_errno \
|
||||
((void(*)(void))_cffi_exports[13])
|
||||
#define _cffi_save_errno \
|
||||
((void(*)(void))_cffi_exports[14])
|
||||
#define _cffi_from_c_char \
|
||||
((PyObject *(*)(char))_cffi_exports[15])
|
||||
#define _cffi_from_c_deref \
|
||||
((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16])
|
||||
#define _cffi_to_c \
|
||||
((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17])
|
||||
#define _cffi_from_c_struct \
|
||||
((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[18])
|
||||
#define _cffi_to_c_wchar_t \
|
||||
((wchar_t(*)(PyObject *))_cffi_exports[19])
|
||||
#define _cffi_from_c_wchar_t \
|
||||
((PyObject *(*)(wchar_t))_cffi_exports[20])
|
||||
#define _cffi_to_c_long_double \
|
||||
((long double(*)(PyObject *))_cffi_exports[21])
|
||||
#define _cffi_to_c__Bool \
|
||||
((_Bool(*)(PyObject *))_cffi_exports[22])
|
||||
#define _cffi_prepare_pointer_call_argument \
|
||||
((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23])
|
||||
#define _cffi_convert_array_from_object \
|
||||
((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24])
|
||||
#define _CFFI_NUM_EXPORTS 25
|
||||
|
||||
typedef struct _ctypedescr CTypeDescrObject;
|
||||
|
||||
static void *_cffi_exports[_CFFI_NUM_EXPORTS];
|
||||
|
||||
#define _cffi_type(index) ( \
|
||||
assert((((uintptr_t)_cffi_types[index]) & 1) == 0), \
|
||||
(CTypeDescrObject *)_cffi_types[index])
|
||||
|
||||
static PyObject *_cffi_init(const char *module_name, Py_ssize_t version,
|
||||
const struct _cffi_type_context_s *ctx)
|
||||
{
|
||||
PyObject *module, *o_arg, *new_module;
|
||||
void *raw[] = {
|
||||
(void *)module_name,
|
||||
(void *)version,
|
||||
(void *)_cffi_exports,
|
||||
(void *)ctx,
|
||||
};
|
||||
|
||||
module = PyImport_ImportModule("_cffi_backend");
|
||||
if (module == NULL)
|
||||
goto failure;
|
||||
|
||||
o_arg = PyLong_FromVoidPtr((void *)raw);
|
||||
if (o_arg == NULL)
|
||||
goto failure;
|
||||
|
||||
new_module = PyObject_CallMethod(
|
||||
module, (char *)"_init_cffi_1_0_external_module", (char *)"O", o_arg);
|
||||
|
||||
Py_DECREF(o_arg);
|
||||
Py_DECREF(module);
|
||||
return new_module;
|
||||
|
||||
failure:
|
||||
Py_XDECREF(module);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_CFFI_UNUSED_FN
|
||||
static PyObject **_cffi_unpack_args(PyObject *args_tuple, Py_ssize_t expected,
|
||||
const char *fnname)
|
||||
{
|
||||
if (PyTuple_GET_SIZE(args_tuple) != expected) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.150s() takes exactly %zd arguments (%zd given)",
|
||||
fnname, expected, PyTuple_GET_SIZE(args_tuple));
|
||||
return NULL;
|
||||
}
|
||||
return &PyTuple_GET_ITEM(args_tuple, 0); /* pointer to the first item,
|
||||
the others follow */
|
||||
}
|
||||
|
||||
#endif
|
||||
/********** end CPython-specific section **********/
|
||||
|
||||
|
||||
#define _cffi_array_len(array) (sizeof(array) / sizeof((array)[0]))
|
||||
|
||||
#define _cffi_prim_int(size, sign) \
|
||||
((size) == 1 ? ((sign) ? _CFFI_PRIM_INT8 : _CFFI_PRIM_UINT8) : \
|
||||
(size) == 2 ? ((sign) ? _CFFI_PRIM_INT16 : _CFFI_PRIM_UINT16) : \
|
||||
(size) == 4 ? ((sign) ? _CFFI_PRIM_INT32 : _CFFI_PRIM_UINT32) : \
|
||||
(size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \
|
||||
_CFFI__UNKNOWN_PRIM)
|
||||
|
||||
#define _cffi_prim_float(size) \
|
||||
((size) == sizeof(float) ? _CFFI_PRIM_FLOAT : \
|
||||
(size) == sizeof(double) ? _CFFI_PRIM_DOUBLE : \
|
||||
(size) == sizeof(long double) ? _CFFI__UNKNOWN_LONG_DOUBLE : \
|
||||
_CFFI__UNKNOWN_FLOAT_PRIM)
|
||||
|
||||
#define _cffi_check_int(got, got_nonpos, expected) \
|
||||
((got_nonpos) == (expected <= 0) && \
|
||||
(got) == (unsigned long long)expected)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -55,7 +55,8 @@ class FFI(object):
|
|||
# _cffi_backend.so compiled.
|
||||
import _cffi_backend as backend
|
||||
from . import __version__
|
||||
assert backend.__version__ == __version__
|
||||
assert backend.__version__ == __version__, \
|
||||
"version mismatch, %s != %s" % (backend.__version__, __version__)
|
||||
# (If you insist you can also try to pass the option
|
||||
# 'backend=backend_ctypes.CTypesBackend()', but don't
|
||||
# rely on it! It's probably not going to work well.)
|
||||
|
|
@ -69,6 +70,8 @@ class FFI(object):
|
|||
self._function_caches = []
|
||||
self._libraries = []
|
||||
self._cdefsources = []
|
||||
self._included_ffis = []
|
||||
self._windows_unicode = None
|
||||
if hasattr(backend, 'set_ffi'):
|
||||
backend.set_ffi(self)
|
||||
for name in backend.__dict__:
|
||||
|
|
@ -77,6 +80,7 @@ class FFI(object):
|
|||
#
|
||||
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'):
|
||||
|
|
@ -105,6 +109,11 @@ class FFI(object):
|
|||
if override:
|
||||
for cache in self._function_caches:
|
||||
cache.clear()
|
||||
finishlist = self._parser._recomplete
|
||||
if finishlist:
|
||||
self._parser._recomplete = []
|
||||
for tp in finishlist:
|
||||
tp.finish_backend_type(self, finishlist)
|
||||
|
||||
def dlopen(self, name, flags=0):
|
||||
"""Load and return a dynamic library identified by 'name'.
|
||||
|
|
@ -189,13 +198,16 @@ class FFI(object):
|
|||
cdecl = self._typeof(cdecl)
|
||||
return self._backend.alignof(cdecl)
|
||||
|
||||
def offsetof(self, cdecl, fieldname):
|
||||
def offsetof(self, cdecl, *fields_or_indexes):
|
||||
"""Return the offset of the named field inside the given
|
||||
structure, which must be given as a C type name.
|
||||
structure or array, which must be given as a C type name.
|
||||
You can give several field names in case of nested structures.
|
||||
You can also give numeric values which correspond to array
|
||||
items, in case of an array type.
|
||||
"""
|
||||
if isinstance(cdecl, basestring):
|
||||
cdecl = self._typeof(cdecl)
|
||||
return self._backend.typeoffsetof(cdecl, fieldname)[1]
|
||||
return self._typeoffsetof(cdecl, *fields_or_indexes)[1]
|
||||
|
||||
def new(self, cdecl, init=None):
|
||||
"""Allocate an instance according to the specified C type and
|
||||
|
|
@ -224,6 +236,30 @@ class FFI(object):
|
|||
cdecl = self._typeof(cdecl)
|
||||
return self._backend.newp(cdecl, init)
|
||||
|
||||
def new_allocator(self, alloc=None, free=None,
|
||||
should_clear_after_alloc=True):
|
||||
"""Return a new allocator, i.e. a function that behaves like ffi.new()
|
||||
but uses the provided low-level 'alloc' and 'free' functions.
|
||||
|
||||
'alloc' is called with the size as argument. If it returns NULL, a
|
||||
MemoryError is raised. 'free' is called with the result of 'alloc'
|
||||
as argument. Both can be either Python function or directly C
|
||||
functions. If 'free' is None, then no free function is called.
|
||||
If both 'alloc' and 'free' are None, the default is used.
|
||||
|
||||
If 'should_clear_after_alloc' is set to False, then the memory
|
||||
returned by 'alloc' is assumed to be already cleared (or you are
|
||||
fine with garbage); otherwise CFFI will clear it.
|
||||
"""
|
||||
compiled_ffi = self._backend.FFI()
|
||||
allocator = compiled_ffi.new_allocator(alloc, free,
|
||||
should_clear_after_alloc)
|
||||
def allocate(cdecl, init=None):
|
||||
if isinstance(cdecl, basestring):
|
||||
cdecl = self._typeof(cdecl)
|
||||
return allocator(cdecl, init)
|
||||
return allocate
|
||||
|
||||
def cast(self, cdecl, source):
|
||||
"""Similar to a C cast: returns an instance of the named C
|
||||
type initialized with the given 'source'. The source is
|
||||
|
|
@ -264,7 +300,33 @@ class FFI(object):
|
|||
"""
|
||||
return self._backend.buffer(cdata, size)
|
||||
|
||||
def callback(self, cdecl, python_callable=None, error=None):
|
||||
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 memmove(self, dest, src, n):
|
||||
"""ffi.memmove(dest, src, n) copies n bytes of memory from src to dest.
|
||||
|
||||
Like the C function memmove(), the memory areas may overlap;
|
||||
apart from that it behaves like the C function memcpy().
|
||||
|
||||
'src' can be any cdata ptr or array, or any Python buffer object.
|
||||
'dest' can be any cdata ptr or array, or a writable Python buffer
|
||||
object. The size to copy, 'n', is always measured in bytes.
|
||||
|
||||
Unlike other methods, this one supports all Python buffer including
|
||||
byte strings and bytearrays---but it still does not support
|
||||
non-contiguous buffers.
|
||||
"""
|
||||
return self._backend.memmove(dest, src, n)
|
||||
|
||||
def callback(self, cdecl, python_callable=None, error=None, onerror=None):
|
||||
"""Return a callback object or a decorator making such a
|
||||
callback object. 'cdecl' must name a C function pointer type.
|
||||
The callback invokes the specified 'python_callable' (which may
|
||||
|
|
@ -276,7 +338,8 @@ class FFI(object):
|
|||
if not callable(python_callable):
|
||||
raise TypeError("the 'python_callable' argument "
|
||||
"is not callable")
|
||||
return self._backend.callback(cdecl, python_callable, error)
|
||||
return self._backend.callback(cdecl, python_callable,
|
||||
error, onerror)
|
||||
if isinstance(cdecl, basestring):
|
||||
cdecl = self._typeof(cdecl, consider_function_as_funcptr=True)
|
||||
if python_callable is None:
|
||||
|
|
@ -305,6 +368,13 @@ class FFI(object):
|
|||
data. Later, when this new cdata object is garbage-collected,
|
||||
'destructor(old_cdata_object)' will be called.
|
||||
"""
|
||||
try:
|
||||
gcp = self._backend.gcp
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
return gcp(cdata, destructor)
|
||||
#
|
||||
with self._lock:
|
||||
try:
|
||||
gc_weakrefs = self.gc_weakrefs
|
||||
|
|
@ -335,9 +405,23 @@ class FFI(object):
|
|||
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
|
||||
|
||||
|
|
@ -356,15 +440,29 @@ class FFI(object):
|
|||
with self._lock:
|
||||
return model.pointer_cache(self, ctype)
|
||||
|
||||
def addressof(self, cdata, field=None):
|
||||
def addressof(self, cdata, *fields_or_indexes):
|
||||
"""Return the address of a <cdata 'struct-or-union'>.
|
||||
If 'field' is specified, return the address of this field.
|
||||
If 'fields_or_indexes' are given, returns the address of that
|
||||
field or array item in the structure or array, recursively in
|
||||
case of nested structures.
|
||||
"""
|
||||
ctype = self._backend.typeof(cdata)
|
||||
ctype, offset = self._backend.typeoffsetof(ctype, field)
|
||||
if fields_or_indexes:
|
||||
ctype, offset = self._typeoffsetof(ctype, *fields_or_indexes)
|
||||
else:
|
||||
if ctype.kind == "pointer":
|
||||
raise TypeError("addressof(pointer)")
|
||||
offset = 0
|
||||
ctypeptr = self._pointer_to(ctype)
|
||||
return self._backend.rawaddressof(ctypeptr, cdata, offset)
|
||||
|
||||
def _typeoffsetof(self, ctype, field_or_index, *fields_or_indexes):
|
||||
ctype, offset = self._backend.typeoffsetof(ctype, field_or_index)
|
||||
for field1 in fields_or_indexes:
|
||||
ctype, offset1 = self._backend.typeoffsetof(ctype, field1, 1)
|
||||
offset += offset1
|
||||
return ctype, offset
|
||||
|
||||
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,
|
||||
|
|
@ -374,12 +472,19 @@ class FFI(object):
|
|||
variables, which must anyway be accessed directly from the
|
||||
lib object returned by the original FFI instance.
|
||||
"""
|
||||
if not isinstance(ffi_to_include, FFI):
|
||||
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)
|
||||
self._cdefsources.append('[')
|
||||
self._cdefsources.extend(ffi_to_include._cdefsources)
|
||||
self._cdefsources.append(']')
|
||||
self._included_ffis.append(ffi_to_include)
|
||||
|
||||
def new_handle(self, x):
|
||||
return self._backend.newp_handle(self.BVoidP, x)
|
||||
|
|
@ -387,6 +492,112 @@ class FFI(object):
|
|||
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 set_source(self, module_name, source, source_extension='.c', **kwds):
|
||||
if hasattr(self, '_assigned_source'):
|
||||
raise ValueError("set_source() cannot be called several times "
|
||||
"per ffi object")
|
||||
if not isinstance(module_name, basestring):
|
||||
raise TypeError("'module_name' must be a string")
|
||||
self._assigned_source = (str(module_name), source,
|
||||
source_extension, kwds)
|
||||
|
||||
def distutils_extension(self, tmpdir='build', verbose=True):
|
||||
from distutils.dir_util import mkpath
|
||||
from .recompiler import recompile
|
||||
#
|
||||
if not hasattr(self, '_assigned_source'):
|
||||
if hasattr(self, 'verifier'): # fallback, 'tmpdir' ignored
|
||||
return self.verifier.get_extension()
|
||||
raise ValueError("set_source() must be called before"
|
||||
" distutils_extension()")
|
||||
module_name, source, source_extension, kwds = self._assigned_source
|
||||
if source is None:
|
||||
raise TypeError("distutils_extension() is only for C extension "
|
||||
"modules, not for dlopen()-style pure Python "
|
||||
"modules")
|
||||
mkpath(tmpdir)
|
||||
ext, updated = recompile(self, module_name,
|
||||
source, tmpdir=tmpdir, extradir=tmpdir,
|
||||
source_extension=source_extension,
|
||||
call_c_compiler=False, **kwds)
|
||||
if verbose:
|
||||
if updated:
|
||||
sys.stderr.write("regenerated: %r\n" % (ext.sources[0],))
|
||||
else:
|
||||
sys.stderr.write("not modified: %r\n" % (ext.sources[0],))
|
||||
return ext
|
||||
|
||||
def emit_c_code(self, filename):
|
||||
from .recompiler import recompile
|
||||
#
|
||||
if not hasattr(self, '_assigned_source'):
|
||||
raise ValueError("set_source() must be called before emit_c_code()")
|
||||
module_name, source, source_extension, kwds = self._assigned_source
|
||||
if source is None:
|
||||
raise TypeError("emit_c_code() is only for C extension modules, "
|
||||
"not for dlopen()-style pure Python modules")
|
||||
recompile(self, module_name, source,
|
||||
c_file=filename, call_c_compiler=False, **kwds)
|
||||
|
||||
def emit_python_code(self, filename):
|
||||
from .recompiler import recompile
|
||||
#
|
||||
if not hasattr(self, '_assigned_source'):
|
||||
raise ValueError("set_source() must be called before emit_c_code()")
|
||||
module_name, source, source_extension, kwds = self._assigned_source
|
||||
if source is not None:
|
||||
raise TypeError("emit_python_code() is only for dlopen()-style "
|
||||
"pure Python modules, not for C extension modules")
|
||||
recompile(self, module_name, source,
|
||||
c_file=filename, call_c_compiler=False, **kwds)
|
||||
|
||||
def compile(self, tmpdir='.'):
|
||||
from .recompiler import recompile
|
||||
#
|
||||
if not hasattr(self, '_assigned_source'):
|
||||
raise ValueError("set_source() must be called before compile()")
|
||||
module_name, source, source_extension, kwds = self._assigned_source
|
||||
return recompile(self, module_name, source, tmpdir=tmpdir,
|
||||
source_extension=source_extension, **kwds)
|
||||
|
||||
|
||||
def _load_backend_lib(backend, name, flags):
|
||||
if name is None:
|
||||
|
|
@ -414,7 +625,7 @@ def _make_ffi_library(ffi, libname, flags):
|
|||
def make_accessor_locked(name):
|
||||
key = 'function ' + name
|
||||
if key in ffi._parser._declarations:
|
||||
tp = ffi._parser._declarations[key]
|
||||
tp, _ = ffi._parser._declarations[key]
|
||||
BType = ffi._get_cached_btype(tp)
|
||||
try:
|
||||
value = backendlib.load_function(BType, name)
|
||||
|
|
@ -425,7 +636,7 @@ def _make_ffi_library(ffi, libname, flags):
|
|||
#
|
||||
key = 'variable ' + name
|
||||
if key in ffi._parser._declarations:
|
||||
tp = ffi._parser._declarations[key]
|
||||
tp, _ = ffi._parser._declarations[key]
|
||||
BType = ffi._get_cached_btype(tp)
|
||||
read_variable = backendlib.read_variable
|
||||
write_variable = backendlib.write_variable
|
||||
|
|
@ -436,12 +647,23 @@ def _make_ffi_library(ffi, libname, flags):
|
|||
#
|
||||
if not copied_enums:
|
||||
from . import model
|
||||
for key, tp in ffi._parser._declarations.items():
|
||||
error = None
|
||||
for key, (tp, _) in ffi._parser._declarations.items():
|
||||
if not isinstance(tp, model.EnumType):
|
||||
continue
|
||||
try:
|
||||
tp.check_not_partial()
|
||||
except Exception as e:
|
||||
error = e
|
||||
continue
|
||||
for enumname, enumval in zip(tp.enumerators, tp.enumvalues):
|
||||
if enumname not in library.__dict__:
|
||||
library.__dict__[enumname] = enumval
|
||||
if error is not None:
|
||||
if name in library.__dict__:
|
||||
return # ignore error, about a different enum
|
||||
raise error
|
||||
|
||||
for key, val in ffi._parser._int_constants.items():
|
||||
if key not in library.__dict__:
|
||||
library.__dict__[key] = val
|
||||
|
|
@ -450,6 +672,11 @@ def _make_ffi_library(ffi, libname, flags):
|
|||
if name in library.__dict__:
|
||||
return
|
||||
#
|
||||
key = 'constant ' + name
|
||||
if key in ffi._parser._declarations:
|
||||
raise NotImplementedError("fetching a non-integer constant "
|
||||
"after dlopen()")
|
||||
#
|
||||
raise AttributeError(name)
|
||||
#
|
||||
def make_accessor(name):
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@ import ctypes, ctypes.util, operator, sys
|
|||
from . import model
|
||||
|
||||
if sys.version_info < (3,):
|
||||
integer_types = (int, long)
|
||||
bytechr = chr
|
||||
else:
|
||||
unicode = str
|
||||
integer_types = int
|
||||
long = int
|
||||
xrange = range
|
||||
bytechr = lambda num: bytes([num])
|
||||
|
||||
|
|
@ -169,6 +168,7 @@ class CTypesGenericArray(CTypesData):
|
|||
class CTypesGenericPtr(CTypesData):
|
||||
__slots__ = ['_address', '_as_ctype_ptr']
|
||||
_automatic_casts = False
|
||||
kind = "pointer"
|
||||
|
||||
@classmethod
|
||||
def _newp(cls, init):
|
||||
|
|
@ -180,7 +180,7 @@ class CTypesGenericPtr(CTypesData):
|
|||
address = 0
|
||||
elif isinstance(source, CTypesData):
|
||||
address = source._cast_to_integer()
|
||||
elif isinstance(source, integer_types):
|
||||
elif isinstance(source, (int, long)):
|
||||
address = source
|
||||
else:
|
||||
raise TypeError("bad type for cast to %r: %r" %
|
||||
|
|
@ -357,7 +357,7 @@ class CTypesBackend(object):
|
|||
is_signed = (ctype(-1).value == -1)
|
||||
#
|
||||
def _cast_source_to_int(source):
|
||||
if isinstance(source, (integer_types, float)):
|
||||
if isinstance(source, (int, long, float)):
|
||||
source = int(source)
|
||||
elif isinstance(source, CTypesData):
|
||||
source = source._cast_to_integer()
|
||||
|
|
@ -370,10 +370,12 @@ class CTypesBackend(object):
|
|||
(CTypesPrimitive, type(source).__name__))
|
||||
return source
|
||||
#
|
||||
kind1 = kind
|
||||
class CTypesPrimitive(CTypesGenericPrimitive):
|
||||
__slots__ = ['_value']
|
||||
_ctype = ctype
|
||||
_reftypename = '%s &' % name
|
||||
kind = kind1
|
||||
|
||||
def __init__(self, value):
|
||||
self._value = value
|
||||
|
|
@ -396,7 +398,7 @@ class CTypesBackend(object):
|
|||
if kind == 'bool':
|
||||
@classmethod
|
||||
def _cast_from(cls, source):
|
||||
if not isinstance(source, (integer_types, float)):
|
||||
if not isinstance(source, (int, long, float)):
|
||||
source = _cast_source_to_int(source)
|
||||
return cls(bool(source))
|
||||
def __int__(self):
|
||||
|
|
@ -435,7 +437,7 @@ class CTypesBackend(object):
|
|||
if kind == 'int' or kind == 'byte' or kind == 'bool':
|
||||
@staticmethod
|
||||
def _to_ctypes(x):
|
||||
if not isinstance(x, integer_types):
|
||||
if not isinstance(x, (int, long)):
|
||||
if isinstance(x, CTypesData):
|
||||
x = int(x)
|
||||
else:
|
||||
|
|
@ -462,7 +464,7 @@ class CTypesBackend(object):
|
|||
if kind == 'float':
|
||||
@staticmethod
|
||||
def _to_ctypes(x):
|
||||
if not isinstance(x, (integer_types, float, CTypesData)):
|
||||
if not isinstance(x, (int, long, float, CTypesData)):
|
||||
raise TypeError("float expected, got %s" %
|
||||
type(x).__name__)
|
||||
return ctype(x).value
|
||||
|
|
@ -526,14 +528,14 @@ class CTypesBackend(object):
|
|||
self._own = True
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, integer_types):
|
||||
if isinstance(other, (int, long)):
|
||||
return self._new_pointer_at(self._address +
|
||||
other * self._bitem_size)
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
def __sub__(self, other):
|
||||
if isinstance(other, integer_types):
|
||||
if isinstance(other, (int, long)):
|
||||
return self._new_pointer_at(self._address -
|
||||
other * self._bitem_size)
|
||||
elif type(self) is type(other):
|
||||
|
|
@ -608,7 +610,7 @@ class CTypesBackend(object):
|
|||
|
||||
def __init__(self, init):
|
||||
if length is None:
|
||||
if isinstance(init, integer_types):
|
||||
if isinstance(init, (int, long)):
|
||||
len1 = init
|
||||
init = None
|
||||
elif kind == 'char' and isinstance(init, bytes):
|
||||
|
|
@ -683,7 +685,7 @@ class CTypesBackend(object):
|
|||
return CTypesPtr._arg_to_ctypes(value)
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, integer_types):
|
||||
if isinstance(other, (int, long)):
|
||||
return CTypesPtr._new_pointer_at(
|
||||
ctypes.addressof(self._blob) +
|
||||
other * ctypes.sizeof(BItem._ctype))
|
||||
|
|
@ -703,12 +705,13 @@ class CTypesBackend(object):
|
|||
class struct_or_union(base_ctypes_class):
|
||||
pass
|
||||
struct_or_union.__name__ = '%s_%s' % (kind, name)
|
||||
kind1 = kind
|
||||
#
|
||||
class CTypesStructOrUnion(CTypesBaseStructOrUnion):
|
||||
__slots__ = ['_blob']
|
||||
_ctype = struct_or_union
|
||||
_reftypename = '%s &' % (name,)
|
||||
_kind = kind
|
||||
_kind = kind = kind1
|
||||
#
|
||||
CTypesStructOrUnion._fix_class()
|
||||
return CTypesStructOrUnion
|
||||
|
|
@ -986,7 +989,8 @@ class CTypesBackend(object):
|
|||
def cast(self, BType, source):
|
||||
return BType._cast_from(source)
|
||||
|
||||
def callback(self, BType, source, error):
|
||||
def callback(self, BType, source, error, onerror):
|
||||
assert onerror is None # XXX not implemented
|
||||
return BType(source, error)
|
||||
|
||||
typeof = type
|
||||
|
|
@ -994,27 +998,42 @@ class CTypesBackend(object):
|
|||
def getcname(self, BType, replace_with):
|
||||
return BType._get_c_name(replace_with)
|
||||
|
||||
def typeoffsetof(self, BType, fieldname):
|
||||
if fieldname is not None and issubclass(BType, CTypesGenericPtr):
|
||||
BType = BType._BItem
|
||||
if not issubclass(BType, CTypesBaseStructOrUnion):
|
||||
raise TypeError("expected a struct or union ctype")
|
||||
if fieldname is None:
|
||||
return (BType, 0)
|
||||
else:
|
||||
def typeoffsetof(self, BType, fieldname, num=0):
|
||||
if isinstance(fieldname, str):
|
||||
if num == 0 and issubclass(BType, CTypesGenericPtr):
|
||||
BType = BType._BItem
|
||||
if not issubclass(BType, CTypesBaseStructOrUnion):
|
||||
raise TypeError("expected a struct or union ctype")
|
||||
BField = BType._bfield_types[fieldname]
|
||||
if BField is Ellipsis:
|
||||
raise TypeError("not supported for bitfields")
|
||||
return (BField, BType._offsetof(fieldname))
|
||||
elif isinstance(fieldname, (int, long)):
|
||||
if issubclass(BType, CTypesGenericArray):
|
||||
BType = BType._CTPtr
|
||||
if not issubclass(BType, CTypesGenericPtr):
|
||||
raise TypeError("expected an array or ptr ctype")
|
||||
BItem = BType._BItem
|
||||
offset = BItem._get_size() * fieldname
|
||||
if offset > sys.maxsize:
|
||||
raise OverflowError
|
||||
return (BItem, offset)
|
||||
else:
|
||||
raise TypeError(type(fieldname))
|
||||
|
||||
def rawaddressof(self, BTypePtr, cdata, offset):
|
||||
def rawaddressof(self, BTypePtr, cdata, offset=None):
|
||||
if isinstance(cdata, CTypesBaseStructOrUnion):
|
||||
ptr = ctypes.pointer(type(cdata)._to_ctypes(cdata))
|
||||
elif isinstance(cdata, CTypesGenericPtr):
|
||||
if offset is None or not issubclass(type(cdata)._BItem,
|
||||
CTypesBaseStructOrUnion):
|
||||
raise TypeError("unexpected cdata type")
|
||||
ptr = type(cdata)._to_ctypes(cdata)
|
||||
elif isinstance(cdata, CTypesGenericArray):
|
||||
ptr = type(cdata)._to_ctypes(cdata)
|
||||
else:
|
||||
raise TypeError("expected a <cdata 'struct-or-union'>")
|
||||
if offset != 0:
|
||||
if offset:
|
||||
ptr = ctypes.cast(
|
||||
ctypes.c_void_p(
|
||||
ctypes.cast(ptr, ctypes.c_void_p).value + offset),
|
||||
|
|
|
|||
176
Linux_x86_64/lib/python3.4/site-packages/cffi/cffi_opcode.py
Normal file
176
Linux_x86_64/lib/python3.4/site-packages/cffi/cffi_opcode.py
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
|
||||
class CffiOp(object):
|
||||
def __init__(self, op, arg):
|
||||
self.op = op
|
||||
self.arg = arg
|
||||
|
||||
def as_c_expr(self):
|
||||
if self.op is None:
|
||||
assert isinstance(self.arg, str)
|
||||
return '(_cffi_opcode_t)(%s)' % (self.arg,)
|
||||
classname = CLASS_NAME[self.op]
|
||||
return '_CFFI_OP(_CFFI_OP_%s, %s)' % (classname, self.arg)
|
||||
|
||||
def as_python_bytes(self):
|
||||
if self.op is None and self.arg.isdigit():
|
||||
value = int(self.arg) # non-negative: '-' not in self.arg
|
||||
if value >= 2**31:
|
||||
raise OverflowError("cannot emit %r: limited to 2**31-1"
|
||||
% (self.arg,))
|
||||
return format_four_bytes(value)
|
||||
if isinstance(self.arg, str):
|
||||
from .ffiplatform import VerificationError
|
||||
raise VerificationError("cannot emit to Python: %r" % (self.arg,))
|
||||
return format_four_bytes((self.arg << 8) | self.op)
|
||||
|
||||
def __str__(self):
|
||||
classname = CLASS_NAME.get(self.op, self.op)
|
||||
return '(%s %s)' % (classname, self.arg)
|
||||
|
||||
def format_four_bytes(num):
|
||||
return '\\x%02X\\x%02X\\x%02X\\x%02X' % (
|
||||
(num >> 24) & 0xFF,
|
||||
(num >> 16) & 0xFF,
|
||||
(num >> 8) & 0xFF,
|
||||
(num ) & 0xFF)
|
||||
|
||||
OP_PRIMITIVE = 1
|
||||
OP_POINTER = 3
|
||||
OP_ARRAY = 5
|
||||
OP_OPEN_ARRAY = 7
|
||||
OP_STRUCT_UNION = 9
|
||||
OP_ENUM = 11
|
||||
OP_FUNCTION = 13
|
||||
OP_FUNCTION_END = 15
|
||||
OP_NOOP = 17
|
||||
OP_BITFIELD = 19
|
||||
OP_TYPENAME = 21
|
||||
OP_CPYTHON_BLTN_V = 23 # varargs
|
||||
OP_CPYTHON_BLTN_N = 25 # noargs
|
||||
OP_CPYTHON_BLTN_O = 27 # O (i.e. a single arg)
|
||||
OP_CONSTANT = 29
|
||||
OP_CONSTANT_INT = 31
|
||||
OP_GLOBAL_VAR = 33
|
||||
OP_DLOPEN_FUNC = 35
|
||||
OP_DLOPEN_CONST = 37
|
||||
OP_GLOBAL_VAR_F = 39
|
||||
|
||||
PRIM_VOID = 0
|
||||
PRIM_BOOL = 1
|
||||
PRIM_CHAR = 2
|
||||
PRIM_SCHAR = 3
|
||||
PRIM_UCHAR = 4
|
||||
PRIM_SHORT = 5
|
||||
PRIM_USHORT = 6
|
||||
PRIM_INT = 7
|
||||
PRIM_UINT = 8
|
||||
PRIM_LONG = 9
|
||||
PRIM_ULONG = 10
|
||||
PRIM_LONGLONG = 11
|
||||
PRIM_ULONGLONG = 12
|
||||
PRIM_FLOAT = 13
|
||||
PRIM_DOUBLE = 14
|
||||
PRIM_LONGDOUBLE = 15
|
||||
|
||||
PRIM_WCHAR = 16
|
||||
PRIM_INT8 = 17
|
||||
PRIM_UINT8 = 18
|
||||
PRIM_INT16 = 19
|
||||
PRIM_UINT16 = 20
|
||||
PRIM_INT32 = 21
|
||||
PRIM_UINT32 = 22
|
||||
PRIM_INT64 = 23
|
||||
PRIM_UINT64 = 24
|
||||
PRIM_INTPTR = 25
|
||||
PRIM_UINTPTR = 26
|
||||
PRIM_PTRDIFF = 27
|
||||
PRIM_SIZE = 28
|
||||
PRIM_SSIZE = 29
|
||||
PRIM_INT_LEAST8 = 30
|
||||
PRIM_UINT_LEAST8 = 31
|
||||
PRIM_INT_LEAST16 = 32
|
||||
PRIM_UINT_LEAST16 = 33
|
||||
PRIM_INT_LEAST32 = 34
|
||||
PRIM_UINT_LEAST32 = 35
|
||||
PRIM_INT_LEAST64 = 36
|
||||
PRIM_UINT_LEAST64 = 37
|
||||
PRIM_INT_FAST8 = 38
|
||||
PRIM_UINT_FAST8 = 39
|
||||
PRIM_INT_FAST16 = 40
|
||||
PRIM_UINT_FAST16 = 41
|
||||
PRIM_INT_FAST32 = 42
|
||||
PRIM_UINT_FAST32 = 43
|
||||
PRIM_INT_FAST64 = 44
|
||||
PRIM_UINT_FAST64 = 45
|
||||
PRIM_INTMAX = 46
|
||||
PRIM_UINTMAX = 47
|
||||
|
||||
_NUM_PRIM = 48
|
||||
_UNKNOWN_PRIM = -1
|
||||
_UNKNOWN_FLOAT_PRIM = -2
|
||||
_UNKNOWN_LONG_DOUBLE = -3
|
||||
|
||||
PRIMITIVE_TO_INDEX = {
|
||||
'char': PRIM_CHAR,
|
||||
'short': PRIM_SHORT,
|
||||
'int': PRIM_INT,
|
||||
'long': PRIM_LONG,
|
||||
'long long': PRIM_LONGLONG,
|
||||
'signed char': PRIM_SCHAR,
|
||||
'unsigned char': PRIM_UCHAR,
|
||||
'unsigned short': PRIM_USHORT,
|
||||
'unsigned int': PRIM_UINT,
|
||||
'unsigned long': PRIM_ULONG,
|
||||
'unsigned long long': PRIM_ULONGLONG,
|
||||
'float': PRIM_FLOAT,
|
||||
'double': PRIM_DOUBLE,
|
||||
'long double': PRIM_LONGDOUBLE,
|
||||
'_Bool': PRIM_BOOL,
|
||||
'wchar_t': PRIM_WCHAR,
|
||||
'int8_t': PRIM_INT8,
|
||||
'uint8_t': PRIM_UINT8,
|
||||
'int16_t': PRIM_INT16,
|
||||
'uint16_t': PRIM_UINT16,
|
||||
'int32_t': PRIM_INT32,
|
||||
'uint32_t': PRIM_UINT32,
|
||||
'int64_t': PRIM_INT64,
|
||||
'uint64_t': PRIM_UINT64,
|
||||
'intptr_t': PRIM_INTPTR,
|
||||
'uintptr_t': PRIM_UINTPTR,
|
||||
'ptrdiff_t': PRIM_PTRDIFF,
|
||||
'size_t': PRIM_SIZE,
|
||||
'ssize_t': PRIM_SSIZE,
|
||||
'int_least8_t': PRIM_INT_LEAST8,
|
||||
'uint_least8_t': PRIM_UINT_LEAST8,
|
||||
'int_least16_t': PRIM_INT_LEAST16,
|
||||
'uint_least16_t': PRIM_UINT_LEAST16,
|
||||
'int_least32_t': PRIM_INT_LEAST32,
|
||||
'uint_least32_t': PRIM_UINT_LEAST32,
|
||||
'int_least64_t': PRIM_INT_LEAST64,
|
||||
'uint_least64_t': PRIM_UINT_LEAST64,
|
||||
'int_fast8_t': PRIM_INT_FAST8,
|
||||
'uint_fast8_t': PRIM_UINT_FAST8,
|
||||
'int_fast16_t': PRIM_INT_FAST16,
|
||||
'uint_fast16_t': PRIM_UINT_FAST16,
|
||||
'int_fast32_t': PRIM_INT_FAST32,
|
||||
'uint_fast32_t': PRIM_UINT_FAST32,
|
||||
'int_fast64_t': PRIM_INT_FAST64,
|
||||
'uint_fast64_t': PRIM_UINT_FAST64,
|
||||
'intmax_t': PRIM_INTMAX,
|
||||
'uintmax_t': PRIM_UINTMAX,
|
||||
}
|
||||
|
||||
F_UNION = 0x01
|
||||
F_CHECK_FIELDS = 0x02
|
||||
F_PACKED = 0x04
|
||||
F_EXTERNAL = 0x08
|
||||
F_OPAQUE = 0x10
|
||||
|
||||
G_FLAGS = dict([('_CFFI_' + _key, globals()[_key])
|
||||
for _key in ['F_UNION', 'F_CHECK_FIELDS', 'F_PACKED',
|
||||
'F_EXTERNAL', 'F_OPAQUE']])
|
||||
|
||||
CLASS_NAME = {}
|
||||
for _name, _value in list(globals().items()):
|
||||
if _name.startswith('OP_') and isinstance(_value, int):
|
||||
CLASS_NAME[_value] = _name[3:]
|
||||
|
|
@ -29,6 +29,9 @@ def resolve_common_type(commontype):
|
|||
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 @@ def win_common_types(maxsize):
|
|||
"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 @@ def win_common_types(maxsize):
|
|||
|
||||
"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 @@ def win_common_types(maxsize):
|
|||
"PBYTE": "BYTE *",
|
||||
"PCHAR": "CHAR *",
|
||||
"PCSTR": "const CHAR *",
|
||||
"PCTSTR": "LPCWSTR",
|
||||
"PCWSTR": "const WCHAR *",
|
||||
"PDWORD": "DWORD *",
|
||||
"PDWORDLONG": "DWORDLONG *",
|
||||
|
|
@ -200,9 +198,6 @@ def win_common_types(maxsize):
|
|||
"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 @@ def win_common_types(maxsize):
|
|||
"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
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
from . import api, model
|
||||
from .commontypes import COMMON_TYPES, resolve_common_type
|
||||
try:
|
||||
|
|
@ -16,15 +15,20 @@ try:
|
|||
except ImportError:
|
||||
lock = None
|
||||
|
||||
_r_comment = re.compile(r"/\*.*?\*/|//.*?$", re.DOTALL | re.MULTILINE)
|
||||
_r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)\s+(.*?)$",
|
||||
re.MULTILINE)
|
||||
_r_comment = re.compile(r"/\*.*?\*/|//([^\n\\]|\\.)*?$",
|
||||
re.DOTALL | re.MULTILINE)
|
||||
_r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)"
|
||||
r"\b((?:[^\n\\]|\\.)*?)$",
|
||||
re.DOTALL | re.MULTILINE)
|
||||
_r_partial_enum = re.compile(r"=\s*\.\.\.\s*[,}]|\.\.\.\s*\}")
|
||||
_r_enum_dotdotdot = re.compile(r"__dotdotdot\d+__$")
|
||||
_r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]")
|
||||
_r_words = re.compile(r"\w+|\S")
|
||||
_parser_cache = None
|
||||
_r_int_literal = re.compile(r"^0?x?[0-9a-f]+u?l?$", re.IGNORECASE)
|
||||
_r_int_literal = re.compile(r"-?0?x?[0-9a-f]+[lu]*$", re.IGNORECASE)
|
||||
_r_stdcall1 = re.compile(r"\b(__stdcall|WINAPI)\b")
|
||||
_r_stdcall2 = re.compile(r"[(]\s*(__stdcall|WINAPI)\b")
|
||||
_r_cdecl = re.compile(r"\b__cdecl\b")
|
||||
|
||||
def _get_parser():
|
||||
global _parser_cache
|
||||
|
|
@ -40,8 +44,17 @@ def _preprocess(csource):
|
|||
macros = {}
|
||||
for match in _r_define.finditer(csource):
|
||||
macroname, macrovalue = match.groups()
|
||||
macrovalue = macrovalue.replace('\\\n', '').strip()
|
||||
macros[macroname] = macrovalue
|
||||
csource = _r_define.sub('', csource)
|
||||
# BIG HACK: replace WINAPI or __stdcall with "volatile const".
|
||||
# It doesn't make sense for the return type of a function to be
|
||||
# "volatile volatile const", so we abuse it to detect __stdcall...
|
||||
# Hack number 2 is that "int(volatile *fptr)();" is not valid C
|
||||
# syntax, so we place the "volatile" before the opening parenthesis.
|
||||
csource = _r_stdcall2.sub(' volatile volatile const(', csource)
|
||||
csource = _r_stdcall1.sub(' volatile volatile const ', csource)
|
||||
csource = _r_cdecl.sub(' ', csource)
|
||||
# Replace "[...]" with "[__dotdotdotarray__]"
|
||||
csource = _r_partial_array.sub('[__dotdotdotarray__]', csource)
|
||||
# Replace "...}" with "__dotdotdotNUM__}". This construction should
|
||||
|
|
@ -73,9 +86,13 @@ def _common_type_names(csource):
|
|||
# but should be fine for all the common types.
|
||||
look_for_words = set(COMMON_TYPES)
|
||||
look_for_words.add(';')
|
||||
look_for_words.add(',')
|
||||
look_for_words.add('(')
|
||||
look_for_words.add(')')
|
||||
look_for_words.add('typedef')
|
||||
words_used = set()
|
||||
is_typedef = False
|
||||
paren = 0
|
||||
previous_word = ''
|
||||
for word in _r_words.findall(csource):
|
||||
if word in look_for_words:
|
||||
|
|
@ -86,6 +103,15 @@ def _common_type_names(csource):
|
|||
is_typedef = False
|
||||
elif word == 'typedef':
|
||||
is_typedef = True
|
||||
paren = 0
|
||||
elif word == '(':
|
||||
paren += 1
|
||||
elif word == ')':
|
||||
paren -= 1
|
||||
elif word == ',':
|
||||
if is_typedef and paren == 0:
|
||||
words_used.discard(previous_word)
|
||||
look_for_words.discard(previous_word)
|
||||
else: # word in COMMON_TYPES
|
||||
words_used.add(word)
|
||||
previous_word = word
|
||||
|
|
@ -96,11 +122,14 @@ class Parser(object):
|
|||
|
||||
def __init__(self):
|
||||
self._declarations = {}
|
||||
self._included_declarations = set()
|
||||
self._anonymous_counter = 0
|
||||
self._structnode2type = weakref.WeakKeyDictionary()
|
||||
self._override = False
|
||||
self._packed = False
|
||||
self._int_constants = {}
|
||||
self._recomplete = []
|
||||
self._uses_new_feature = None
|
||||
|
||||
def _parse(self, csource):
|
||||
csource, macros = _preprocess(csource)
|
||||
|
|
@ -187,9 +216,10 @@ class Parser(object):
|
|||
if not decl.name:
|
||||
raise api.CDefError("typedef does not declare any name",
|
||||
decl)
|
||||
quals = 0
|
||||
if (isinstance(decl.type.type, pycparser.c_ast.IdentifierType)
|
||||
and decl.type.type.names == ['__dotdotdot__']):
|
||||
realtype = model.unknown_type(decl.name)
|
||||
and decl.type.type.names[-1] == '__dotdotdot__'):
|
||||
realtype = self._get_unknown_type(decl)
|
||||
elif (isinstance(decl.type, pycparser.c_ast.PtrDecl) and
|
||||
isinstance(decl.type.type, pycparser.c_ast.TypeDecl) and
|
||||
isinstance(decl.type.type.type,
|
||||
|
|
@ -197,8 +227,9 @@ class Parser(object):
|
|||
decl.type.type.type.names == ['__dotdotdot__']):
|
||||
realtype = model.unknown_ptr_type(decl.name)
|
||||
else:
|
||||
realtype = self._get_type(decl.type, name=decl.name)
|
||||
self._declare('typedef ' + decl.name, realtype)
|
||||
realtype, quals = self._get_type_and_quals(
|
||||
decl.type, name=decl.name)
|
||||
self._declare('typedef ' + decl.name, realtype, quals=quals)
|
||||
else:
|
||||
raise api.CDefError("unrecognized construct", decl)
|
||||
except api.FFIError as e:
|
||||
|
|
@ -209,60 +240,84 @@ class Parser(object):
|
|||
|
||||
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
|
||||
|
||||
def _add_integer_constant(self, name, int_str):
|
||||
int_str = int_str.lower().rstrip("ul")
|
||||
neg = int_str.startswith('-')
|
||||
if neg:
|
||||
int_str = int_str[1:]
|
||||
# "010" is not valid oct in py3
|
||||
if (int_str.startswith("0") and int_str != '0'
|
||||
and not int_str.startswith("0x")):
|
||||
int_str = "0o" + int_str[1:]
|
||||
pyvalue = int(int_str, 0)
|
||||
if neg:
|
||||
pyvalue = -pyvalue
|
||||
self._add_constants(name, pyvalue)
|
||||
self._declare('macro ' + name, pyvalue)
|
||||
|
||||
def _process_macros(self, macros):
|
||||
for key, value in macros.items():
|
||||
value = value.strip()
|
||||
match = _r_int_literal.search(value)
|
||||
if match is not None:
|
||||
int_str = match.group(0).lower().rstrip("ul")
|
||||
|
||||
# "010" is not valid oct in py3
|
||||
if (int_str.startswith("0") and
|
||||
int_str != "0" and
|
||||
not int_str.startswith("0x")):
|
||||
int_str = "0o" + int_str[1:]
|
||||
|
||||
pyvalue = int(int_str, 0)
|
||||
self._add_constants(key, pyvalue)
|
||||
if _r_int_literal.match(value):
|
||||
self._add_integer_constant(key, value)
|
||||
elif value == '...':
|
||||
self._declare('macro ' + key, value)
|
||||
else:
|
||||
raise api.CDefError('only supports the syntax "#define '
|
||||
'%s ..." (literally) or "#define '
|
||||
'%s 0x1FF" for now' % (key, key))
|
||||
raise api.CDefError(
|
||||
'only supports one of the following syntax:\n'
|
||||
' #define %s ... (literally dot-dot-dot)\n'
|
||||
' #define %s NUMBER (with NUMBER an integer'
|
||||
' constant, decimal/hex/octal)\n'
|
||||
'got:\n'
|
||||
' #define %s %s'
|
||||
% (key, key, key, value))
|
||||
|
||||
def _parse_decl(self, decl):
|
||||
node = decl.type
|
||||
if isinstance(node, pycparser.c_ast.FuncDecl):
|
||||
tp = self._get_type(node, name=decl.name)
|
||||
tp, quals = self._get_type_and_quals(node, name=decl.name)
|
||||
assert isinstance(tp, model.RawFunctionType)
|
||||
tp = self._get_type_pointer(tp)
|
||||
tp = self._get_type_pointer(tp, quals)
|
||||
self._declare('function ' + decl.name, tp)
|
||||
else:
|
||||
if isinstance(node, pycparser.c_ast.Struct):
|
||||
# XXX do we need self._declare in any of those?
|
||||
if node.decls is not None:
|
||||
self._get_struct_union_enum_type('struct', node)
|
||||
self._get_struct_union_enum_type('struct', node)
|
||||
elif isinstance(node, pycparser.c_ast.Union):
|
||||
if node.decls is not None:
|
||||
self._get_struct_union_enum_type('union', node)
|
||||
self._get_struct_union_enum_type('union', node)
|
||||
elif isinstance(node, pycparser.c_ast.Enum):
|
||||
if node.values is not None:
|
||||
self._get_struct_union_enum_type('enum', node)
|
||||
self._get_struct_union_enum_type('enum', node)
|
||||
elif not decl.name:
|
||||
raise api.CDefError("construct does not declare any variable",
|
||||
decl)
|
||||
#
|
||||
if decl.name:
|
||||
tp = self._get_type(node, partial_length_ok=True)
|
||||
if self._is_constant_globalvar(node):
|
||||
self._declare('constant ' + decl.name, tp)
|
||||
tp, quals = self._get_type_and_quals(node,
|
||||
partial_length_ok=True)
|
||||
if tp.is_raw_function:
|
||||
tp = self._get_type_pointer(tp, quals)
|
||||
self._declare('function ' + decl.name, tp)
|
||||
elif (tp.is_integer_type() and
|
||||
hasattr(decl, 'init') and
|
||||
hasattr(decl.init, 'value') and
|
||||
_r_int_literal.match(decl.init.value)):
|
||||
self._add_integer_constant(decl.name, decl.init.value)
|
||||
elif (tp.is_integer_type() and
|
||||
isinstance(decl.init, pycparser.c_ast.UnaryOp) and
|
||||
decl.init.op == '-' and
|
||||
hasattr(decl.init.expr, 'value') and
|
||||
_r_int_literal.match(decl.init.expr.value)):
|
||||
self._add_integer_constant(decl.name,
|
||||
'-' + decl.init.expr.value)
|
||||
elif (quals & model.Q_CONST) and not tp.is_array_type:
|
||||
self._declare('constant ' + decl.name, tp, quals=quals)
|
||||
else:
|
||||
self._declare('variable ' + decl.name, tp)
|
||||
self._declare('variable ' + decl.name, tp, quals=quals)
|
||||
|
||||
def parse_type(self, cdecl):
|
||||
ast, macros = self._parse('void __dummy(\n%s\n);' % cdecl)[:2]
|
||||
|
|
@ -270,34 +325,51 @@ class Parser(object):
|
|||
exprnode = ast.ext[-1].type.args.params[0]
|
||||
if isinstance(exprnode, pycparser.c_ast.ID):
|
||||
raise api.CDefError("unknown identifier '%s'" % (exprnode.name,))
|
||||
return self._get_type(exprnode.type)
|
||||
tp, quals = self._get_type_and_quals(exprnode.type)
|
||||
return tp
|
||||
|
||||
def _declare(self, name, obj):
|
||||
def _declare(self, name, obj, included=False, quals=0):
|
||||
if name in self._declarations:
|
||||
if self._declarations[name] is obj:
|
||||
prevobj, prevquals = self._declarations[name]
|
||||
if prevobj is obj and prevquals == quals:
|
||||
return
|
||||
if not self._override:
|
||||
raise api.FFIError(
|
||||
"multiple declarations of %s (for interactive usage, "
|
||||
"try cdef(xx, override=True))" % (name,))
|
||||
assert '__dotdotdot__' not in name.split()
|
||||
self._declarations[name] = obj
|
||||
self._declarations[name] = (obj, quals)
|
||||
if included:
|
||||
self._included_declarations.add(obj)
|
||||
|
||||
def _get_type_pointer(self, type, const=False):
|
||||
def _extract_quals(self, type):
|
||||
quals = 0
|
||||
if isinstance(type, (pycparser.c_ast.TypeDecl,
|
||||
pycparser.c_ast.PtrDecl)):
|
||||
if 'const' in type.quals:
|
||||
quals |= model.Q_CONST
|
||||
if 'restrict' in type.quals:
|
||||
quals |= model.Q_RESTRICT
|
||||
return quals
|
||||
|
||||
def _get_type_pointer(self, type, quals, declname=None):
|
||||
if isinstance(type, model.RawFunctionType):
|
||||
return type.as_function_pointer()
|
||||
if const:
|
||||
return model.ConstPointerType(type)
|
||||
return model.PointerType(type)
|
||||
if (isinstance(type, model.StructOrUnionOrEnum) and
|
||||
type.name.startswith('$') and type.name[1:].isdigit() and
|
||||
type.forcename is None and declname is not None):
|
||||
return model.NamedPointerType(type, declname, quals)
|
||||
return model.PointerType(type, quals)
|
||||
|
||||
def _get_type(self, typenode, name=None, partial_length_ok=False):
|
||||
def _get_type_and_quals(self, typenode, name=None, partial_length_ok=False):
|
||||
# first, dereference typedefs, if we have it already parsed, we're good
|
||||
if (isinstance(typenode, pycparser.c_ast.TypeDecl) and
|
||||
isinstance(typenode.type, pycparser.c_ast.IdentifierType) and
|
||||
len(typenode.type.names) == 1 and
|
||||
('typedef ' + typenode.type.names[0]) in self._declarations):
|
||||
type = self._declarations['typedef ' + typenode.type.names[0]]
|
||||
return type
|
||||
tp, quals = self._declarations['typedef ' + typenode.type.names[0]]
|
||||
quals |= self._extract_quals(typenode)
|
||||
return tp, quals
|
||||
#
|
||||
if isinstance(typenode, pycparser.c_ast.ArrayDecl):
|
||||
# array type
|
||||
|
|
@ -306,15 +378,19 @@ class Parser(object):
|
|||
else:
|
||||
length = self._parse_constant(
|
||||
typenode.dim, partial_length_ok=partial_length_ok)
|
||||
return model.ArrayType(self._get_type(typenode.type), length)
|
||||
tp, quals = self._get_type_and_quals(typenode.type,
|
||||
partial_length_ok=partial_length_ok)
|
||||
return model.ArrayType(tp, length), quals
|
||||
#
|
||||
if isinstance(typenode, pycparser.c_ast.PtrDecl):
|
||||
# pointer type
|
||||
const = (isinstance(typenode.type, pycparser.c_ast.TypeDecl)
|
||||
and 'const' in typenode.type.quals)
|
||||
return self._get_type_pointer(self._get_type(typenode.type), const)
|
||||
itemtype, itemquals = self._get_type_and_quals(typenode.type)
|
||||
tp = self._get_type_pointer(itemtype, itemquals, declname=name)
|
||||
quals = self._extract_quals(typenode)
|
||||
return tp, quals
|
||||
#
|
||||
if isinstance(typenode, pycparser.c_ast.TypeDecl):
|
||||
quals = self._extract_quals(typenode)
|
||||
type = typenode.type
|
||||
if isinstance(type, pycparser.c_ast.IdentifierType):
|
||||
# assume a primitive type. get it from .names, but reduce
|
||||
|
|
@ -342,35 +418,38 @@ class Parser(object):
|
|||
names = newnames + names
|
||||
ident = ' '.join(names)
|
||||
if ident == 'void':
|
||||
return model.void_type
|
||||
return model.void_type, quals
|
||||
if ident == '__dotdotdot__':
|
||||
raise api.FFIError(':%d: bad usage of "..."' %
|
||||
typenode.coord.line)
|
||||
return resolve_common_type(ident)
|
||||
return resolve_common_type(ident), quals
|
||||
#
|
||||
if isinstance(type, pycparser.c_ast.Struct):
|
||||
# 'struct foobar'
|
||||
return self._get_struct_union_enum_type('struct', type, name)
|
||||
tp = self._get_struct_union_enum_type('struct', type, name)
|
||||
return tp, quals
|
||||
#
|
||||
if isinstance(type, pycparser.c_ast.Union):
|
||||
# 'union foobar'
|
||||
return self._get_struct_union_enum_type('union', type, name)
|
||||
tp = self._get_struct_union_enum_type('union', type, name)
|
||||
return tp, quals
|
||||
#
|
||||
if isinstance(type, pycparser.c_ast.Enum):
|
||||
# 'enum foobar'
|
||||
return self._get_struct_union_enum_type('enum', type, name)
|
||||
tp = self._get_struct_union_enum_type('enum', type, name)
|
||||
return tp, quals
|
||||
#
|
||||
if isinstance(typenode, pycparser.c_ast.FuncDecl):
|
||||
# a function type
|
||||
return self._parse_function_type(typenode, name)
|
||||
return self._parse_function_type(typenode, name), 0
|
||||
#
|
||||
# nested anonymous structs or unions end up here
|
||||
if isinstance(typenode, pycparser.c_ast.Struct):
|
||||
return self._get_struct_union_enum_type('struct', typenode, name,
|
||||
nested=True)
|
||||
nested=True), 0
|
||||
if isinstance(typenode, pycparser.c_ast.Union):
|
||||
return self._get_struct_union_enum_type('union', typenode, name,
|
||||
nested=True)
|
||||
nested=True), 0
|
||||
#
|
||||
raise api.FFIError(":%d: bad or unsupported type declaration" %
|
||||
typenode.coord.line)
|
||||
|
|
@ -389,31 +468,28 @@ class Parser(object):
|
|||
raise api.CDefError(
|
||||
"%s: a function with only '(...)' as argument"
|
||||
" is not correct C" % (funcname or 'in expression'))
|
||||
elif (len(params) == 1 and
|
||||
isinstance(params[0].type, pycparser.c_ast.TypeDecl) and
|
||||
isinstance(params[0].type.type, pycparser.c_ast.IdentifierType)
|
||||
and list(params[0].type.type.names) == ['void']):
|
||||
del params[0]
|
||||
args = [self._as_func_arg(self._get_type(argdeclnode.type))
|
||||
args = [self._as_func_arg(*self._get_type_and_quals(argdeclnode.type))
|
||||
for argdeclnode in params]
|
||||
result = self._get_type(typenode.type)
|
||||
return model.RawFunctionType(tuple(args), result, ellipsis)
|
||||
if not ellipsis and args == [model.void_type]:
|
||||
args = []
|
||||
result, quals = self._get_type_and_quals(typenode.type)
|
||||
# the 'quals' on the result type are ignored. HACK: we absure them
|
||||
# to detect __stdcall functions: we textually replace "__stdcall"
|
||||
# with "volatile volatile const" above.
|
||||
abi = None
|
||||
if hasattr(typenode.type, 'quals'): # else, probable syntax error anyway
|
||||
if typenode.type.quals[-3:] == ['volatile', 'volatile', 'const']:
|
||||
abi = '__stdcall'
|
||||
return model.RawFunctionType(tuple(args), result, ellipsis, abi)
|
||||
|
||||
def _as_func_arg(self, type):
|
||||
def _as_func_arg(self, type, quals):
|
||||
if isinstance(type, model.ArrayType):
|
||||
return model.PointerType(type.item)
|
||||
return model.PointerType(type.item, quals)
|
||||
elif isinstance(type, model.RawFunctionType):
|
||||
return type.as_function_pointer()
|
||||
else:
|
||||
return type
|
||||
|
||||
def _is_constant_globalvar(self, typenode):
|
||||
if isinstance(typenode, pycparser.c_ast.PtrDecl):
|
||||
return 'const' in typenode.quals
|
||||
if isinstance(typenode, pycparser.c_ast.TypeDecl):
|
||||
return 'const' in typenode.quals
|
||||
return False
|
||||
|
||||
def _get_struct_union_enum_type(self, kind, type, name=None, nested=False):
|
||||
# First, a level of caching on the exact 'type' node of the AST.
|
||||
# This is obscure, but needed because pycparser "unrolls" declarations
|
||||
|
|
@ -452,7 +528,7 @@ class Parser(object):
|
|||
else:
|
||||
explicit_name = name
|
||||
key = '%s %s' % (kind, name)
|
||||
tp = self._declarations.get(key, None)
|
||||
tp, _ = self._declarations.get(key, (None, None))
|
||||
#
|
||||
if tp is None:
|
||||
if kind == 'struct':
|
||||
|
|
@ -460,6 +536,8 @@ class Parser(object):
|
|||
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,))
|
||||
|
|
@ -492,6 +570,7 @@ class Parser(object):
|
|||
fldnames = []
|
||||
fldtypes = []
|
||||
fldbitsize = []
|
||||
fldquals = []
|
||||
for decl in type.decls:
|
||||
if (isinstance(decl.type, pycparser.c_ast.IdentifierType) and
|
||||
''.join(decl.type.names) == '__dotdotdot__'):
|
||||
|
|
@ -505,7 +584,8 @@ class Parser(object):
|
|||
else:
|
||||
bitsize = self._parse_constant(decl.bitsize)
|
||||
self._partial_length = False
|
||||
type = self._get_type(decl.type, partial_length_ok=True)
|
||||
type, fqual = self._get_type_and_quals(decl.type,
|
||||
partial_length_ok=True)
|
||||
if self._partial_length:
|
||||
self._make_partial(tp, nested)
|
||||
if isinstance(type, model.StructType) and type.partial:
|
||||
|
|
@ -513,14 +593,19 @@ class Parser(object):
|
|||
fldnames.append(decl.name or '')
|
||||
fldtypes.append(type)
|
||||
fldbitsize.append(bitsize)
|
||||
fldquals.append(fqual)
|
||||
tp.fldnames = tuple(fldnames)
|
||||
tp.fldtypes = tuple(fldtypes)
|
||||
tp.fldbitsize = tuple(fldbitsize)
|
||||
tp.fldquals = tuple(fldquals)
|
||||
if fldbitsize != [-1] * len(fldbitsize):
|
||||
if isinstance(tp, model.StructType) and tp.partial:
|
||||
raise NotImplementedError("%s: using both bitfields and '...;'"
|
||||
% (tp,))
|
||||
tp.packed = self._packed
|
||||
if tp.completed: # must be re-completed: it is not opaque any more
|
||||
tp.completed = 0
|
||||
self._recomplete.append(tp)
|
||||
return tp
|
||||
|
||||
def _make_partial(self, tp, nested):
|
||||
|
|
@ -532,9 +617,24 @@ class Parser(object):
|
|||
|
||||
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 == '-'):
|
||||
|
|
@ -555,19 +655,21 @@ class Parser(object):
|
|||
|
||||
def _build_enum_type(self, explicit_name, decls):
|
||||
if decls is not None:
|
||||
enumerators1 = [enum.name for enum in decls.enumerators]
|
||||
enumerators = [s for s in enumerators1
|
||||
if not _r_enum_dotdotdot.match(s)]
|
||||
partial = len(enumerators) < len(enumerators1)
|
||||
enumerators = tuple(enumerators)
|
||||
partial = False
|
||||
enumerators = []
|
||||
enumvalues = []
|
||||
nextenumvalue = 0
|
||||
for enum in decls.enumerators[:len(enumerators)]:
|
||||
for enum in decls.enumerators:
|
||||
if _r_enum_dotdotdot.match(enum.name):
|
||||
partial = True
|
||||
continue
|
||||
if enum.value is not None:
|
||||
nextenumvalue = self._parse_constant(enum.value)
|
||||
enumerators.append(enum.name)
|
||||
enumvalues.append(nextenumvalue)
|
||||
self._add_constants(enum.name, nextenumvalue)
|
||||
nextenumvalue += 1
|
||||
enumerators = tuple(enumerators)
|
||||
enumvalues = tuple(enumvalues)
|
||||
tp = model.EnumType(explicit_name, enumerators, enumvalues)
|
||||
tp.partial = partial
|
||||
|
|
@ -576,9 +678,35 @@ class Parser(object):
|
|||
return tp
|
||||
|
||||
def include(self, other):
|
||||
for name, tp in other._declarations.items():
|
||||
for name, (tp, quals) in other._declarations.items():
|
||||
if name.startswith('anonymous $enum_$'):
|
||||
continue # fix for test_anonymous_enum_include
|
||||
kind = name.split(' ', 1)[0]
|
||||
if kind in ('typedef', 'struct', 'union', 'enum'):
|
||||
self._declare(name, tp)
|
||||
if kind in ('struct', 'union', 'enum', 'anonymous', 'typedef'):
|
||||
self._declare(name, tp, included=True, quals=quals)
|
||||
for k, v in other._int_constants.items():
|
||||
self._add_constants(k, v)
|
||||
|
||||
def _get_unknown_type(self, decl):
|
||||
typenames = decl.type.type.names
|
||||
assert typenames[-1] == '__dotdotdot__'
|
||||
if len(typenames) == 1:
|
||||
return model.unknown_type(decl.name)
|
||||
|
||||
if (typenames[:-1] == ['float'] or
|
||||
typenames[:-1] == ['double']):
|
||||
# not for 'long double' so far
|
||||
result = model.UnknownFloatType(decl.name)
|
||||
else:
|
||||
for t in typenames[:-1]:
|
||||
if t not in ['int', 'short', 'long', 'signed',
|
||||
'unsigned', 'char']:
|
||||
raise api.FFIError(':%d: bad usage of "..."' %
|
||||
decl.coord.line)
|
||||
result = model.UnknownIntegerType(decl.name)
|
||||
|
||||
if self._uses_new_feature is None:
|
||||
self._uses_new_feature = "'typedef %s... %s'" % (
|
||||
' '.join(typenames[:-1]), decl.name)
|
||||
|
||||
return result
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import os
|
||||
import sys, os
|
||||
|
||||
|
||||
class VerificationError(Exception):
|
||||
|
|
@ -11,6 +11,9 @@ class VerificationMissing(Exception):
|
|||
"""
|
||||
|
||||
|
||||
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]
|
||||
|
|
|
|||
|
|
@ -2,18 +2,21 @@ from weakref import ref
|
|||
|
||||
|
||||
class GcWeakrefs(object):
|
||||
# code copied and adapted from WeakKeyDictionary.
|
||||
|
||||
def __init__(self, ffi):
|
||||
self.ffi = ffi
|
||||
self.data = data = {}
|
||||
def remove(k):
|
||||
destructor, cdata = data.pop(k)
|
||||
destructor(cdata)
|
||||
self.remove = remove
|
||||
self.data = {}
|
||||
|
||||
def build(self, cdata, destructor):
|
||||
# make a new cdata of the same type as the original one
|
||||
new_cdata = self.ffi.cast(self.ffi._backend.typeof(cdata), cdata)
|
||||
self.data[ref(new_cdata, self.remove)] = destructor, cdata
|
||||
#
|
||||
def remove(key):
|
||||
# careful, this function is not protected by any lock
|
||||
old_key = self.data.pop(index)
|
||||
assert old_key is key
|
||||
destructor(cdata)
|
||||
#
|
||||
key = ref(new_cdata, remove)
|
||||
index = object()
|
||||
self.data[index] = key
|
||||
return new_cdata
|
||||
|
|
|
|||
|
|
@ -1,14 +1,29 @@
|
|||
import types
|
||||
import types, sys
|
||||
import weakref
|
||||
|
||||
from .lock import allocate_lock
|
||||
|
||||
|
||||
# type qualifiers
|
||||
Q_CONST = 0x01
|
||||
Q_RESTRICT = 0x02
|
||||
|
||||
def qualify(quals, replace_with):
|
||||
if quals & Q_CONST:
|
||||
replace_with = ' const ' + replace_with.lstrip()
|
||||
if quals & Q_RESTRICT:
|
||||
# It seems that __restrict is supported by gcc and msvc.
|
||||
# If you hit some different compiler, add a #define in
|
||||
# _cffi_include.h for it (and in its copies, documented there)
|
||||
replace_with = ' __restrict ' + replace_with.lstrip()
|
||||
return replace_with
|
||||
|
||||
|
||||
class BaseTypeByIdentity(object):
|
||||
is_array_type = False
|
||||
is_raw_function = False
|
||||
|
||||
def get_c_name(self, replace_with='', context='a C file'):
|
||||
def get_c_name(self, replace_with='', context='a C file', quals=0):
|
||||
result = self.c_name_with_marker
|
||||
assert result.count('&') == 1
|
||||
# some logic duplication with ffi.getctype()... :-(
|
||||
|
|
@ -18,6 +33,7 @@ class BaseTypeByIdentity(object):
|
|||
replace_with = '(%s)' % replace_with
|
||||
elif not replace_with[0] in '[(':
|
||||
replace_with = ' ' + replace_with
|
||||
replace_with = qualify(quals, replace_with)
|
||||
result = result.replace('&', replace_with)
|
||||
if '$' in result:
|
||||
from .ffiplatform import VerificationError
|
||||
|
|
@ -32,6 +48,9 @@ class BaseTypeByIdentity(object):
|
|||
def has_c_name(self):
|
||||
return '$' not in self._get_c_name()
|
||||
|
||||
def is_integer_type(self):
|
||||
return False
|
||||
|
||||
def get_cached_btype(self, ffi, finishlist, can_delay=False):
|
||||
try:
|
||||
BType = ffi._cached_btypes[self]
|
||||
|
|
@ -73,7 +92,11 @@ class VoidType(BaseType):
|
|||
void_type = VoidType()
|
||||
|
||||
|
||||
class PrimitiveType(BaseType):
|
||||
class BasePrimitiveType(BaseType):
|
||||
pass
|
||||
|
||||
|
||||
class PrimitiveType(BasePrimitiveType):
|
||||
_attrs_ = ('name',)
|
||||
|
||||
ALL_PRIMITIVE_TYPES = {
|
||||
|
|
@ -102,8 +125,26 @@ class PrimitiveType(BaseType):
|
|||
'uint32_t': 'i',
|
||||
'int64_t': 'i',
|
||||
'uint64_t': 'i',
|
||||
'int_least8_t': 'i',
|
||||
'uint_least8_t': 'i',
|
||||
'int_least16_t': 'i',
|
||||
'uint_least16_t': 'i',
|
||||
'int_least32_t': 'i',
|
||||
'uint_least32_t': 'i',
|
||||
'int_least64_t': 'i',
|
||||
'uint_least64_t': 'i',
|
||||
'int_fast8_t': 'i',
|
||||
'uint_fast8_t': 'i',
|
||||
'int_fast16_t': 'i',
|
||||
'uint_fast16_t': 'i',
|
||||
'int_fast32_t': 'i',
|
||||
'uint_fast32_t': 'i',
|
||||
'int_fast64_t': 'i',
|
||||
'uint_fast64_t': 'i',
|
||||
'intptr_t': 'i',
|
||||
'uintptr_t': 'i',
|
||||
'intmax_t': 'i',
|
||||
'uintmax_t': 'i',
|
||||
'ptrdiff_t': 'i',
|
||||
'size_t': 'i',
|
||||
'ssize_t': 'i',
|
||||
|
|
@ -125,19 +166,48 @@ class PrimitiveType(BaseType):
|
|||
return global_cache(self, ffi, 'new_primitive_type', self.name)
|
||||
|
||||
|
||||
class BaseFunctionType(BaseType):
|
||||
_attrs_ = ('args', 'result', 'ellipsis')
|
||||
class UnknownIntegerType(BasePrimitiveType):
|
||||
_attrs_ = ('name',)
|
||||
|
||||
def __init__(self, args, result, ellipsis):
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.c_name_with_marker = name + '&'
|
||||
|
||||
def is_integer_type(self):
|
||||
return True
|
||||
|
||||
def build_backend_type(self, ffi, finishlist):
|
||||
raise NotImplementedError("integer type '%s' can only be used after "
|
||||
"compilation" % self.name)
|
||||
|
||||
class UnknownFloatType(BasePrimitiveType):
|
||||
_attrs_ = ('name', )
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
self.c_name_with_marker = name + '&'
|
||||
|
||||
def build_backend_type(self, ffi, finishlist):
|
||||
raise NotImplementedError("float type '%s' can only be used after "
|
||||
"compilation" % self.name)
|
||||
|
||||
|
||||
class BaseFunctionType(BaseType):
|
||||
_attrs_ = ('args', 'result', 'ellipsis', 'abi')
|
||||
|
||||
def __init__(self, args, result, ellipsis, abi=None):
|
||||
self.args = args
|
||||
self.result = result
|
||||
self.ellipsis = ellipsis
|
||||
self.abi = abi
|
||||
#
|
||||
reprargs = [arg._get_c_name() for arg in self.args]
|
||||
if self.ellipsis:
|
||||
reprargs.append('...')
|
||||
reprargs = reprargs or ['void']
|
||||
replace_with = self._base_pattern % (', '.join(reprargs),)
|
||||
if abi is not None:
|
||||
replace_with = replace_with[:1] + abi + ' ' + replace_with[1:]
|
||||
self.c_name_with_marker = (
|
||||
self.result.c_name_with_marker.replace('&', replace_with))
|
||||
|
||||
|
|
@ -155,7 +225,7 @@ class RawFunctionType(BaseFunctionType):
|
|||
"type, not a pointer-to-function type" % (self,))
|
||||
|
||||
def as_function_pointer(self):
|
||||
return FunctionPtrType(self.args, self.result, self.ellipsis)
|
||||
return FunctionPtrType(self.args, self.result, self.ellipsis, self.abi)
|
||||
|
||||
|
||||
class FunctionPtrType(BaseFunctionType):
|
||||
|
|
@ -166,21 +236,29 @@ class FunctionPtrType(BaseFunctionType):
|
|||
args = []
|
||||
for tp in self.args:
|
||||
args.append(tp.get_cached_btype(ffi, finishlist))
|
||||
abi_args = ()
|
||||
if self.abi == "__stdcall":
|
||||
if not self.ellipsis: # __stdcall ignored for variadic funcs
|
||||
try:
|
||||
abi_args = (ffi._backend.FFI_STDCALL,)
|
||||
except AttributeError:
|
||||
pass
|
||||
return global_cache(self, ffi, 'new_function_type',
|
||||
tuple(args), result, self.ellipsis)
|
||||
tuple(args), result, self.ellipsis, *abi_args)
|
||||
|
||||
def as_raw_function(self):
|
||||
return RawFunctionType(self.args, self.result, self.ellipsis, self.abi)
|
||||
|
||||
|
||||
class PointerType(BaseType):
|
||||
_attrs_ = ('totype',)
|
||||
_base_pattern = " *&"
|
||||
_base_pattern_array = "(*&)"
|
||||
_attrs_ = ('totype', 'quals')
|
||||
|
||||
def __init__(self, totype):
|
||||
def __init__(self, totype, quals=0):
|
||||
self.totype = totype
|
||||
self.quals = quals
|
||||
extra = qualify(quals, " *&")
|
||||
if totype.is_array_type:
|
||||
extra = self._base_pattern_array
|
||||
else:
|
||||
extra = self._base_pattern
|
||||
extra = "(%s)" % (extra.lstrip(),)
|
||||
self.c_name_with_marker = totype.c_name_with_marker.replace('&', extra)
|
||||
|
||||
def build_backend_type(self, ffi, finishlist):
|
||||
|
|
@ -189,10 +267,8 @@ class PointerType(BaseType):
|
|||
|
||||
voidp_type = PointerType(void_type)
|
||||
|
||||
|
||||
class ConstPointerType(PointerType):
|
||||
_base_pattern = " const *&"
|
||||
_base_pattern_array = "(const *&)"
|
||||
def ConstPointerType(totype):
|
||||
return PointerType(totype, Q_CONST)
|
||||
|
||||
const_voidp_type = ConstPointerType(void_type)
|
||||
|
||||
|
|
@ -200,8 +276,8 @@ const_voidp_type = ConstPointerType(void_type)
|
|||
class NamedPointerType(PointerType):
|
||||
_attrs_ = ('totype', 'name')
|
||||
|
||||
def __init__(self, totype, name):
|
||||
PointerType.__init__(self, totype)
|
||||
def __init__(self, totype, name, quals=0):
|
||||
PointerType.__init__(self, totype, quals)
|
||||
self.name = name
|
||||
self.c_name_with_marker = name + '&'
|
||||
|
||||
|
|
@ -219,7 +295,7 @@ class ArrayType(BaseType):
|
|||
elif length == '...':
|
||||
brackets = '&[/*...*/]'
|
||||
else:
|
||||
brackets = '&[%d]' % length
|
||||
brackets = '&[%s]' % length
|
||||
self.c_name_with_marker = (
|
||||
self.item.c_name_with_marker.replace('&', brackets))
|
||||
|
||||
|
|
@ -235,6 +311,8 @@ class ArrayType(BaseType):
|
|||
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',)
|
||||
|
|
@ -255,26 +333,38 @@ class StructOrUnionOrEnum(BaseTypeByIdentity):
|
|||
|
||||
class StructOrUnion(StructOrUnionOrEnum):
|
||||
fixedlayout = None
|
||||
completed = False
|
||||
completed = 0
|
||||
partial = False
|
||||
packed = False
|
||||
|
||||
def __init__(self, name, fldnames, fldtypes, fldbitsize):
|
||||
def __init__(self, name, fldnames, fldtypes, fldbitsize, fldquals=None):
|
||||
self.name = name
|
||||
self.fldnames = fldnames
|
||||
self.fldtypes = fldtypes
|
||||
self.fldbitsize = fldbitsize
|
||||
self.fldquals = fldquals
|
||||
self.build_c_name_with_marker()
|
||||
|
||||
def has_anonymous_struct_fields(self):
|
||||
if self.fldtypes is None:
|
||||
return False
|
||||
for name, type in zip(self.fldnames, self.fldtypes):
|
||||
if name == '' and isinstance(type, StructOrUnion):
|
||||
return True
|
||||
return False
|
||||
|
||||
def enumfields(self):
|
||||
for name, type, bitsize in zip(self.fldnames, self.fldtypes,
|
||||
self.fldbitsize):
|
||||
fldquals = self.fldquals
|
||||
if fldquals is None:
|
||||
fldquals = (0,) * len(self.fldnames)
|
||||
for name, type, bitsize, quals in zip(self.fldnames, self.fldtypes,
|
||||
self.fldbitsize, fldquals):
|
||||
if name == '' and isinstance(type, StructOrUnion):
|
||||
# nested anonymous struct/union
|
||||
for result in type.enumfields():
|
||||
yield result
|
||||
else:
|
||||
yield (name, type, bitsize)
|
||||
yield (name, type, bitsize, quals)
|
||||
|
||||
def force_flatten(self):
|
||||
# force the struct or union to have a declaration that lists
|
||||
|
|
@ -283,13 +373,16 @@ class StructOrUnion(StructOrUnionOrEnum):
|
|||
names = []
|
||||
types = []
|
||||
bitsizes = []
|
||||
for name, type, bitsize in self.enumfields():
|
||||
fldquals = []
|
||||
for name, type, bitsize, quals in self.enumfields():
|
||||
names.append(name)
|
||||
types.append(type)
|
||||
bitsizes.append(bitsize)
|
||||
fldquals.append(quals)
|
||||
self.fldnames = tuple(names)
|
||||
self.fldtypes = tuple(types)
|
||||
self.fldbitsize = tuple(bitsizes)
|
||||
self.fldquals = tuple(fldquals)
|
||||
|
||||
def get_cached_btype(self, ffi, finishlist, can_delay=False):
|
||||
BType = StructOrUnionOrEnum.get_cached_btype(self, ffi, finishlist,
|
||||
|
|
@ -305,12 +398,13 @@ class StructOrUnion(StructOrUnionOrEnum):
|
|||
"for '%s'" % (self.name,))
|
||||
return
|
||||
BType = ffi._cached_btypes[self]
|
||||
if self.fldtypes is None:
|
||||
return # not completing it: it's an opaque struct
|
||||
#
|
||||
self.completed = 1
|
||||
#
|
||||
if self.fixedlayout is None:
|
||||
if self.fldtypes is None:
|
||||
pass # not completing it: it's an opaque struct
|
||||
#
|
||||
elif self.fixedlayout is None:
|
||||
fldtypes = [tp.get_cached_btype(ffi, finishlist)
|
||||
for tp in self.fldtypes]
|
||||
lst = list(zip(self.fldnames, fldtypes, self.fldbitsize))
|
||||
|
|
@ -449,11 +543,12 @@ def unknown_type(name, structname=None):
|
|||
structname = '$%s' % name
|
||||
tp = StructType(structname, None, None, None)
|
||||
tp.force_the_name(name)
|
||||
tp.origin = "unknown_type"
|
||||
return tp
|
||||
|
||||
def unknown_ptr_type(name, structname=None):
|
||||
if structname is None:
|
||||
structname = '*$%s' % name
|
||||
structname = '$$%s' % name
|
||||
tp = StructType(structname, None, None, None)
|
||||
return NamedPointerType(tp, name)
|
||||
|
||||
|
|
@ -478,7 +573,7 @@ def global_cache(srctype, ffi, funcname, *args, **kwds):
|
|||
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
|
||||
|
|
|
|||
167
Linux_x86_64/lib/python3.4/site-packages/cffi/parse_c_type.h
Normal file
167
Linux_x86_64/lib/python3.4/site-packages/cffi/parse_c_type.h
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
|
||||
/* See doc/misc/parse_c_type.rst in the source of CFFI for more information */
|
||||
|
||||
typedef void *_cffi_opcode_t;
|
||||
|
||||
#define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8))
|
||||
#define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode)
|
||||
#define _CFFI_GETARG(cffi_opcode) (((intptr_t)cffi_opcode) >> 8)
|
||||
|
||||
#define _CFFI_OP_PRIMITIVE 1
|
||||
#define _CFFI_OP_POINTER 3
|
||||
#define _CFFI_OP_ARRAY 5
|
||||
#define _CFFI_OP_OPEN_ARRAY 7
|
||||
#define _CFFI_OP_STRUCT_UNION 9
|
||||
#define _CFFI_OP_ENUM 11
|
||||
#define _CFFI_OP_FUNCTION 13
|
||||
#define _CFFI_OP_FUNCTION_END 15
|
||||
#define _CFFI_OP_NOOP 17
|
||||
#define _CFFI_OP_BITFIELD 19
|
||||
#define _CFFI_OP_TYPENAME 21
|
||||
#define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs
|
||||
#define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs
|
||||
#define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg)
|
||||
#define _CFFI_OP_CONSTANT 29
|
||||
#define _CFFI_OP_CONSTANT_INT 31
|
||||
#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
|
||||
#define _CFFI_PRIM_CHAR 2
|
||||
#define _CFFI_PRIM_SCHAR 3
|
||||
#define _CFFI_PRIM_UCHAR 4
|
||||
#define _CFFI_PRIM_SHORT 5
|
||||
#define _CFFI_PRIM_USHORT 6
|
||||
#define _CFFI_PRIM_INT 7
|
||||
#define _CFFI_PRIM_UINT 8
|
||||
#define _CFFI_PRIM_LONG 9
|
||||
#define _CFFI_PRIM_ULONG 10
|
||||
#define _CFFI_PRIM_LONGLONG 11
|
||||
#define _CFFI_PRIM_ULONGLONG 12
|
||||
#define _CFFI_PRIM_FLOAT 13
|
||||
#define _CFFI_PRIM_DOUBLE 14
|
||||
#define _CFFI_PRIM_LONGDOUBLE 15
|
||||
|
||||
#define _CFFI_PRIM_WCHAR 16
|
||||
#define _CFFI_PRIM_INT8 17
|
||||
#define _CFFI_PRIM_UINT8 18
|
||||
#define _CFFI_PRIM_INT16 19
|
||||
#define _CFFI_PRIM_UINT16 20
|
||||
#define _CFFI_PRIM_INT32 21
|
||||
#define _CFFI_PRIM_UINT32 22
|
||||
#define _CFFI_PRIM_INT64 23
|
||||
#define _CFFI_PRIM_UINT64 24
|
||||
#define _CFFI_PRIM_INTPTR 25
|
||||
#define _CFFI_PRIM_UINTPTR 26
|
||||
#define _CFFI_PRIM_PTRDIFF 27
|
||||
#define _CFFI_PRIM_SIZE 28
|
||||
#define _CFFI_PRIM_SSIZE 29
|
||||
#define _CFFI_PRIM_INT_LEAST8 30
|
||||
#define _CFFI_PRIM_UINT_LEAST8 31
|
||||
#define _CFFI_PRIM_INT_LEAST16 32
|
||||
#define _CFFI_PRIM_UINT_LEAST16 33
|
||||
#define _CFFI_PRIM_INT_LEAST32 34
|
||||
#define _CFFI_PRIM_UINT_LEAST32 35
|
||||
#define _CFFI_PRIM_INT_LEAST64 36
|
||||
#define _CFFI_PRIM_UINT_LEAST64 37
|
||||
#define _CFFI_PRIM_INT_FAST8 38
|
||||
#define _CFFI_PRIM_UINT_FAST8 39
|
||||
#define _CFFI_PRIM_INT_FAST16 40
|
||||
#define _CFFI_PRIM_UINT_FAST16 41
|
||||
#define _CFFI_PRIM_INT_FAST32 42
|
||||
#define _CFFI_PRIM_UINT_FAST32 43
|
||||
#define _CFFI_PRIM_INT_FAST64 44
|
||||
#define _CFFI_PRIM_UINT_FAST64 45
|
||||
#define _CFFI_PRIM_INTMAX 46
|
||||
#define _CFFI_PRIM_UINTMAX 47
|
||||
|
||||
#define _CFFI__NUM_PRIM 48
|
||||
#define _CFFI__UNKNOWN_PRIM (-1)
|
||||
#define _CFFI__UNKNOWN_FLOAT_PRIM (-2)
|
||||
#define _CFFI__UNKNOWN_LONG_DOUBLE (-3)
|
||||
|
||||
|
||||
struct _cffi_global_s {
|
||||
const char *name;
|
||||
void *address;
|
||||
_cffi_opcode_t type_op;
|
||||
void *size_or_direct_fn; // OP_GLOBAL_VAR: size, or 0 if unknown
|
||||
// OP_CPYTHON_BLTN_*: addr of direct function
|
||||
};
|
||||
|
||||
struct _cffi_getconst_s {
|
||||
unsigned long long value;
|
||||
const struct _cffi_type_context_s *ctx;
|
||||
int gindex;
|
||||
};
|
||||
|
||||
struct _cffi_struct_union_s {
|
||||
const char *name;
|
||||
int type_index; // -> _cffi_types, on a OP_STRUCT_UNION
|
||||
int flags; // _CFFI_F_* flags below
|
||||
size_t size;
|
||||
int alignment;
|
||||
int first_field_index; // -> _cffi_fields array
|
||||
int num_fields;
|
||||
};
|
||||
#define _CFFI_F_UNION 0x01 // is a union, not a struct
|
||||
#define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the
|
||||
// "standard layout" or if some are missing
|
||||
#define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed struct
|
||||
#define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include()
|
||||
#define _CFFI_F_OPAQUE 0x10 // opaque
|
||||
|
||||
struct _cffi_field_s {
|
||||
const char *name;
|
||||
size_t field_offset;
|
||||
size_t field_size;
|
||||
_cffi_opcode_t field_type_op;
|
||||
};
|
||||
|
||||
struct _cffi_enum_s {
|
||||
const char *name;
|
||||
int type_index; // -> _cffi_types, on a OP_ENUM
|
||||
int type_prim; // _CFFI_PRIM_xxx
|
||||
const char *enumerators; // comma-delimited string
|
||||
};
|
||||
|
||||
struct _cffi_typename_s {
|
||||
const char *name;
|
||||
int type_index; /* if opaque, points to a possibly artificial
|
||||
OP_STRUCT which is itself opaque */
|
||||
};
|
||||
|
||||
struct _cffi_type_context_s {
|
||||
_cffi_opcode_t *types;
|
||||
const struct _cffi_global_s *globals;
|
||||
const struct _cffi_field_s *fields;
|
||||
const struct _cffi_struct_union_s *struct_unions;
|
||||
const struct _cffi_enum_s *enums;
|
||||
const struct _cffi_typename_s *typenames;
|
||||
int num_globals;
|
||||
int num_struct_unions;
|
||||
int num_enums;
|
||||
int num_typenames;
|
||||
const char *const *includes;
|
||||
int num_types;
|
||||
int flags; /* future extension */
|
||||
};
|
||||
|
||||
struct _cffi_parse_info_s {
|
||||
const struct _cffi_type_context_s *ctx;
|
||||
_cffi_opcode_t *output;
|
||||
unsigned int output_size;
|
||||
size_t error_location;
|
||||
const char *error_message;
|
||||
};
|
||||
|
||||
#ifdef _CFFI_INTERNAL
|
||||
static int parse_c_type(struct _cffi_parse_info_s *info, const char *input);
|
||||
static int search_in_globals(const struct _cffi_type_context_s *ctx,
|
||||
const char *search, size_t search_len);
|
||||
static int search_in_struct_unions(const struct _cffi_type_context_s *ctx,
|
||||
const char *search, size_t search_len);
|
||||
#endif
|
||||
1290
Linux_x86_64/lib/python3.4/site-packages/cffi/recompiler.py
Normal file
1290
Linux_x86_64/lib/python3.4/site-packages/cffi/recompiler.py
Normal file
File diff suppressed because it is too large
Load diff
161
Linux_x86_64/lib/python3.4/site-packages/cffi/setuptools_ext.py
Normal file
161
Linux_x86_64/lib/python3.4/site-packages/cffi/setuptools_ext.py
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
import os
|
||||
|
||||
try:
|
||||
basestring
|
||||
except NameError:
|
||||
# Python 3.x
|
||||
basestring = str
|
||||
|
||||
def error(msg):
|
||||
from distutils.errors import DistutilsSetupError
|
||||
raise DistutilsSetupError(msg)
|
||||
|
||||
|
||||
def execfile(filename, glob):
|
||||
# We use execfile() (here rewritten for Python 3) instead of
|
||||
# __import__() to load the build script. The problem with
|
||||
# a normal import is that in some packages, the intermediate
|
||||
# __init__.py files may already try to import the file that
|
||||
# we are generating.
|
||||
with open(filename) as f:
|
||||
src = f.read()
|
||||
src += '\n' # Python 2.6 compatibility
|
||||
code = compile(src, filename, 'exec')
|
||||
exec(code, glob, glob)
|
||||
|
||||
|
||||
def add_cffi_module(dist, mod_spec):
|
||||
from cffi.api import FFI
|
||||
|
||||
if not isinstance(mod_spec, basestring):
|
||||
error("argument to 'cffi_modules=...' must be a str or a list of str,"
|
||||
" not %r" % (type(mod_spec).__name__,))
|
||||
mod_spec = str(mod_spec)
|
||||
try:
|
||||
build_file_name, ffi_var_name = mod_spec.split(':')
|
||||
except ValueError:
|
||||
error("%r must be of the form 'path/build.py:ffi_variable'" %
|
||||
(mod_spec,))
|
||||
if not os.path.exists(build_file_name):
|
||||
ext = ''
|
||||
rewritten = build_file_name.replace('.', '/') + '.py'
|
||||
if os.path.exists(rewritten):
|
||||
ext = ' (rewrite cffi_modules to [%r])' % (
|
||||
rewritten + ':' + ffi_var_name,)
|
||||
error("%r does not name an existing file%s" % (build_file_name, ext))
|
||||
|
||||
mod_vars = {'__name__': '__cffi__', '__file__': build_file_name}
|
||||
execfile(build_file_name, mod_vars)
|
||||
|
||||
try:
|
||||
ffi = mod_vars[ffi_var_name]
|
||||
except KeyError:
|
||||
error("%r: object %r not found in module" % (mod_spec,
|
||||
ffi_var_name))
|
||||
if not isinstance(ffi, FFI):
|
||||
ffi = ffi() # maybe it's a function instead of directly an ffi
|
||||
if not isinstance(ffi, FFI):
|
||||
error("%r is not an FFI instance (got %r)" % (mod_spec,
|
||||
type(ffi).__name__))
|
||||
if not hasattr(ffi, '_assigned_source'):
|
||||
error("%r: the set_source() method was not called" % (mod_spec,))
|
||||
module_name, source, source_extension, kwds = ffi._assigned_source
|
||||
if ffi._windows_unicode:
|
||||
kwds = kwds.copy()
|
||||
ffi._apply_windows_unicode(kwds)
|
||||
|
||||
if source is None:
|
||||
_add_py_module(dist, ffi, module_name)
|
||||
else:
|
||||
_add_c_module(dist, ffi, module_name, source, source_extension, kwds)
|
||||
|
||||
|
||||
def _add_c_module(dist, ffi, module_name, source, source_extension, kwds):
|
||||
from distutils.core import Extension
|
||||
from distutils.command.build_ext import build_ext
|
||||
from distutils.dir_util import mkpath
|
||||
from distutils import log
|
||||
from cffi import recompiler
|
||||
|
||||
allsources = ['$PLACEHOLDER']
|
||||
allsources.extend(kwds.pop('sources', []))
|
||||
ext = Extension(name=module_name, sources=allsources, **kwds)
|
||||
|
||||
def make_mod(tmpdir, pre_run=None):
|
||||
c_file = os.path.join(tmpdir, module_name + source_extension)
|
||||
log.info("generating cffi module %r" % c_file)
|
||||
mkpath(tmpdir)
|
||||
# a setuptools-only, API-only hook: called with the "ext" and "ffi"
|
||||
# arguments just before we turn the ffi into C code. To use it,
|
||||
# subclass the 'distutils.command.build_ext.build_ext' class and
|
||||
# add a method 'def pre_run(self, ext, ffi)'.
|
||||
if pre_run is not None:
|
||||
pre_run(ext, ffi)
|
||||
updated = recompiler.make_c_source(ffi, module_name, source, c_file)
|
||||
if not updated:
|
||||
log.info("already up-to-date")
|
||||
return c_file
|
||||
|
||||
if dist.ext_modules is None:
|
||||
dist.ext_modules = []
|
||||
dist.ext_modules.append(ext)
|
||||
|
||||
base_class = dist.cmdclass.get('build_ext', build_ext)
|
||||
class build_ext_make_mod(base_class):
|
||||
def run(self):
|
||||
if ext.sources[0] == '$PLACEHOLDER':
|
||||
pre_run = getattr(self, 'pre_run', None)
|
||||
ext.sources[0] = make_mod(self.build_temp, pre_run)
|
||||
base_class.run(self)
|
||||
dist.cmdclass['build_ext'] = build_ext_make_mod
|
||||
# NB. multiple runs here will create multiple 'build_ext_make_mod'
|
||||
# classes. Even in this case the 'build_ext' command should be
|
||||
# run once; but just in case, the logic above does nothing if
|
||||
# called again.
|
||||
|
||||
|
||||
def _add_py_module(dist, ffi, module_name):
|
||||
from distutils.dir_util import mkpath
|
||||
from distutils.command.build_py import build_py
|
||||
from distutils.command.build_ext import build_ext
|
||||
from distutils import log
|
||||
from cffi import recompiler
|
||||
|
||||
def generate_mod(py_file):
|
||||
log.info("generating cffi module %r" % py_file)
|
||||
mkpath(os.path.dirname(py_file))
|
||||
updated = recompiler.make_py_source(ffi, module_name, py_file)
|
||||
if not updated:
|
||||
log.info("already up-to-date")
|
||||
|
||||
base_class = dist.cmdclass.get('build_py', build_py)
|
||||
class build_py_make_mod(base_class):
|
||||
def run(self):
|
||||
base_class.run(self)
|
||||
module_path = module_name.split('.')
|
||||
module_path[-1] += '.py'
|
||||
generate_mod(os.path.join(self.build_lib, *module_path))
|
||||
dist.cmdclass['build_py'] = build_py_make_mod
|
||||
|
||||
# the following is only for "build_ext -i"
|
||||
base_class_2 = dist.cmdclass.get('build_ext', build_ext)
|
||||
class build_ext_make_mod(base_class_2):
|
||||
def run(self):
|
||||
base_class_2.run(self)
|
||||
if self.inplace:
|
||||
# from get_ext_fullpath() in distutils/command/build_ext.py
|
||||
module_path = module_name.split('.')
|
||||
package = '.'.join(module_path[:-1])
|
||||
build_py = self.get_finalized_command('build_py')
|
||||
package_dir = build_py.get_package_dir(package)
|
||||
file_name = module_path[-1] + '.py'
|
||||
generate_mod(os.path.join(package_dir, file_name))
|
||||
dist.cmdclass['build_ext'] = build_ext_make_mod
|
||||
|
||||
def cffi_modules(dist, attr, value):
|
||||
assert attr == 'cffi_modules'
|
||||
if isinstance(value, basestring):
|
||||
value = [value]
|
||||
|
||||
for cffi_module in value:
|
||||
add_cffi_module(dist, cffi_module)
|
||||
|
|
@ -65,7 +65,7 @@ class VCPythonEngine(object):
|
|||
# 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,26 @@ class VCPythonEngine(object):
|
|||
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
|
||||
imp.acquire_lock()
|
||||
try:
|
||||
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)
|
||||
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)
|
||||
finally:
|
||||
imp.release_lock()
|
||||
#
|
||||
# call loading_cpy_struct() to get the struct layout inferred by
|
||||
# the C compiler
|
||||
|
|
@ -186,7 +197,10 @@ class VCPythonEngine(object):
|
|||
return library
|
||||
|
||||
def _get_declarations(self):
|
||||
return sorted(self.ffi._parser._declarations.items())
|
||||
lst = [(key, tp) for (key, (tp, qual)) in
|
||||
self.ffi._parser._declarations.items()]
|
||||
lst.sort()
|
||||
return lst
|
||||
|
||||
def _generate(self, step_name):
|
||||
for name, tp in self._get_declarations():
|
||||
|
|
@ -228,7 +242,8 @@ class VCPythonEngine(object):
|
|||
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 +282,8 @@ class VCPythonEngine(object):
|
|||
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 +351,7 @@ class VCPythonEngine(object):
|
|||
prnt = self._prnt
|
||||
numargs = len(tp.args)
|
||||
if numargs == 0:
|
||||
argname = 'no_arg'
|
||||
argname = 'noarg'
|
||||
elif numargs == 1:
|
||||
argname = 'arg0'
|
||||
else:
|
||||
|
|
@ -386,6 +401,9 @@ class VCPythonEngine(object):
|
|||
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,7 +470,8 @@ class VCPythonEngine(object):
|
|||
prnt('static void %s(%s *p)' % (checkfuncname, cname))
|
||||
prnt('{')
|
||||
prnt(' /* only to generate compile-time warnings or errors */')
|
||||
for fname, ftype, fbitsize in tp.enumfields():
|
||||
prnt(' (void)p;')
|
||||
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||
if (isinstance(ftype, model.PrimitiveType)
|
||||
and ftype.is_integer_type()) or fbitsize >= 0:
|
||||
# accept all integers, but complain on float or double
|
||||
|
|
@ -461,7 +480,8 @@ class VCPythonEngine(object):
|
|||
# only accept exactly the type declared.
|
||||
try:
|
||||
prnt(' { %s = &p->%s; (void)tmp; }' % (
|
||||
ftype.get_c_name('*tmp', 'field %r'%fname), fname))
|
||||
ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual),
|
||||
fname))
|
||||
except ffiplatform.VerificationError as e:
|
||||
prnt(' /* %s */' % str(e)) # cannot verify it, ignore
|
||||
prnt('}')
|
||||
|
|
@ -472,7 +492,7 @@ class VCPythonEngine(object):
|
|||
prnt(' static Py_ssize_t nums[] = {')
|
||||
prnt(' sizeof(%s),' % cname)
|
||||
prnt(' offsetof(struct _cffi_aligncheck, y),')
|
||||
for fname, ftype, fbitsize in tp.enumfields():
|
||||
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||
if fbitsize >= 0:
|
||||
continue # xxx ignore fbitsize for now
|
||||
prnt(' offsetof(%s, %s),' % (cname, fname))
|
||||
|
|
@ -482,6 +502,8 @@ class VCPythonEngine(object):
|
|||
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,))
|
||||
|
|
@ -534,7 +556,7 @@ class VCPythonEngine(object):
|
|||
check(layout[0], ffi.sizeof(BStruct), "wrong total size")
|
||||
check(layout[1], ffi.alignof(BStruct), "wrong total alignment")
|
||||
i = 2
|
||||
for fname, ftype, fbitsize in tp.enumfields():
|
||||
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||
if fbitsize >= 0:
|
||||
continue # xxx ignore fbitsize for now
|
||||
check(layout[i], ffi.offsetof(BStruct, fname),
|
||||
|
|
@ -578,7 +600,8 @@ class VCPythonEngine(object):
|
|||
# constants, likely declared with '#define'
|
||||
|
||||
def _generate_cpy_const(self, is_int, name, tp=None, category='const',
|
||||
vartp=None, delayed=True, size_too=False):
|
||||
vartp=None, delayed=True, size_too=False,
|
||||
check_value=None):
|
||||
prnt = self._prnt
|
||||
funcname = '_cffi_%s_%s' % (category, name)
|
||||
prnt('static int %s(PyObject *lib)' % funcname)
|
||||
|
|
@ -590,6 +613,9 @@ class VCPythonEngine(object):
|
|||
else:
|
||||
assert category == 'const'
|
||||
#
|
||||
if check_value is not None:
|
||||
self._check_int_constant_value(name, check_value)
|
||||
#
|
||||
if not is_int:
|
||||
if category == 'var':
|
||||
realexpr = '&' + name
|
||||
|
|
@ -637,6 +663,27 @@ class VCPythonEngine(object):
|
|||
# ----------
|
||||
# enums
|
||||
|
||||
def _check_int_constant_value(self, name, value, err_prefix=''):
|
||||
prnt = self._prnt
|
||||
if value <= 0:
|
||||
prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % (
|
||||
name, name, value))
|
||||
else:
|
||||
prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % (
|
||||
name, name, value))
|
||||
prnt(' char buf[64];')
|
||||
prnt(' if ((%s) <= 0)' % name)
|
||||
prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % name)
|
||||
prnt(' else')
|
||||
prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' %
|
||||
name)
|
||||
prnt(' PyErr_Format(_cffi_VerificationError,')
|
||||
prnt(' "%s%s has the real value %s, not %s",')
|
||||
prnt(' "%s", "%s", buf, "%d");' % (
|
||||
err_prefix, name, value))
|
||||
prnt(' return -1;')
|
||||
prnt(' }')
|
||||
|
||||
def _enum_funcname(self, prefix, name):
|
||||
# "$enum_$1" => "___D_enum____D_1"
|
||||
name = name.replace('$', '___D_')
|
||||
|
|
@ -653,25 +700,8 @@ class VCPythonEngine(object):
|
|||
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) {' % (
|
||||
enumerator, enumerator, enumvalue))
|
||||
else:
|
||||
prnt(' if ((%s) < 0 || (unsigned long)(%s) != %dUL) {' % (
|
||||
enumerator, enumerator, enumvalue))
|
||||
prnt(' char buf[64];')
|
||||
prnt(' if ((%s) < 0)' % enumerator)
|
||||
prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % enumerator)
|
||||
prnt(' else')
|
||||
prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' %
|
||||
enumerator)
|
||||
prnt(' PyErr_Format(_cffi_VerificationError,')
|
||||
prnt(' "enum %s: %s has the real value %s, '
|
||||
'not %s",')
|
||||
prnt(' "%s", "%s", buf, "%d");' % (
|
||||
name, enumerator, enumvalue))
|
||||
prnt(' return -1;')
|
||||
prnt(' }')
|
||||
self._check_int_constant_value(enumerator, enumvalue,
|
||||
"enum %s: " % name)
|
||||
prnt(' return %s;' % self._chained_list_constants[True])
|
||||
self._chained_list_constants[True] = funcname + '(lib)'
|
||||
prnt('}')
|
||||
|
|
@ -695,8 +725,11 @@ class VCPythonEngine(object):
|
|||
# macros: for now only for integers
|
||||
|
||||
def _generate_cpy_macro_decl(self, tp, name):
|
||||
assert tp == '...'
|
||||
self._generate_cpy_const(True, name)
|
||||
if tp == '...':
|
||||
check_value = None
|
||||
else:
|
||||
check_value = tp # an integer
|
||||
self._generate_cpy_const(True, name, check_value=check_value)
|
||||
|
||||
_generate_cpy_macro_collecttype = _generate_nothing
|
||||
_generate_cpy_macro_method = _generate_nothing
|
||||
|
|
@ -783,6 +816,24 @@ cffimod_header = r'''
|
|||
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,15 +879,19 @@ cffimod_header = r'''
|
|||
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) \
|
||||
((type)( \
|
||||
sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \
|
||||
: (type)_cffi_to_c_i8(o)) : \
|
||||
sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \
|
||||
: (type)_cffi_to_c_i16(o)) : \
|
||||
|
|
@ -844,7 +899,7 @@ cffimod_header = r'''
|
|||
: (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 +962,7 @@ static PyObject *_cffi_setup(PyObject *self, PyObject *args)
|
|||
{
|
||||
PyObject *library;
|
||||
int was_alive = (_cffi_types != NULL);
|
||||
(void)self; /* unused */
|
||||
if (!PyArg_ParseTuple(args, "OOO", &_cffi_types, &_cffi_VerificationError,
|
||||
&library))
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -58,12 +58,12 @@ class VGenericEngine(object):
|
|||
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
|
||||
|
|
@ -87,7 +87,10 @@ class VGenericEngine(object):
|
|||
return library
|
||||
|
||||
def _get_declarations(self):
|
||||
return sorted(self.ffi._parser._declarations.items())
|
||||
lst = [(key, tp) for (key, (tp, qual)) in
|
||||
self.ffi._parser._declarations.items()]
|
||||
lst.sort()
|
||||
return lst
|
||||
|
||||
def _generate(self, step_name):
|
||||
for name, tp in self._get_declarations():
|
||||
|
|
@ -149,15 +152,25 @@ class VGenericEngine(object):
|
|||
context = 'argument of %s' % name
|
||||
arglist = [type.get_c_name(' %s' % arg, context)
|
||||
for type, arg in zip(tp.args, argnames)]
|
||||
tpresult = tp.result
|
||||
if isinstance(tpresult, model.StructOrUnion):
|
||||
arglist.insert(0, tpresult.get_c_name(' *r', context))
|
||||
tpresult = model.void_type
|
||||
arglist = ', '.join(arglist) or 'void'
|
||||
wrappername = '_cffi_f_%s' % name
|
||||
self.export_symbols.append(wrappername)
|
||||
funcdecl = ' %s(%s)' % (wrappername, arglist)
|
||||
if tp.abi:
|
||||
abi = tp.abi + ' '
|
||||
else:
|
||||
abi = ''
|
||||
funcdecl = ' %s%s(%s)' % (abi, wrappername, arglist)
|
||||
context = 'result of %s' % name
|
||||
prnt(tp.result.get_c_name(funcdecl, context))
|
||||
prnt(tpresult.get_c_name(funcdecl, context))
|
||||
prnt('{')
|
||||
#
|
||||
if not isinstance(tp.result, model.VoidType):
|
||||
if isinstance(tp.result, model.StructOrUnion):
|
||||
result_code = '*r = '
|
||||
elif not isinstance(tp.result, model.VoidType):
|
||||
result_code = 'return '
|
||||
else:
|
||||
result_code = ''
|
||||
|
|
@ -174,15 +187,26 @@ class VGenericEngine(object):
|
|||
else:
|
||||
indirections = []
|
||||
base_tp = tp
|
||||
if any(isinstance(typ, model.StructOrUnion) for typ in tp.args):
|
||||
if (any(isinstance(typ, model.StructOrUnion) for typ in tp.args)
|
||||
or isinstance(tp.result, model.StructOrUnion)):
|
||||
indirect_args = []
|
||||
for i, typ in enumerate(tp.args):
|
||||
if isinstance(typ, model.StructOrUnion):
|
||||
typ = model.PointerType(typ)
|
||||
indirections.append((i, typ))
|
||||
indirect_args.append(typ)
|
||||
indirect_result = tp.result
|
||||
if isinstance(indirect_result, model.StructOrUnion):
|
||||
if indirect_result.fldtypes is None:
|
||||
raise TypeError("'%s' is used as result type, "
|
||||
"but is opaque" % (
|
||||
indirect_result._get_c_name(),))
|
||||
indirect_result = model.PointerType(indirect_result)
|
||||
indirect_args.insert(0, indirect_result)
|
||||
indirections.insert(0, ("result", indirect_result))
|
||||
indirect_result = model.void_type
|
||||
tp = model.FunctionPtrType(tuple(indirect_args),
|
||||
tp.result, tp.ellipsis)
|
||||
indirect_result, tp.ellipsis)
|
||||
BFunc = self.ffi._get_cached_btype(tp)
|
||||
wrappername = '_cffi_f_%s' % name
|
||||
newfunction = module.load_function(BFunc, wrappername)
|
||||
|
|
@ -195,9 +219,16 @@ class VGenericEngine(object):
|
|||
def _make_struct_wrapper(self, oldfunc, i, tp, base_tp):
|
||||
backend = self.ffi._backend
|
||||
BType = self.ffi._get_cached_btype(tp)
|
||||
def newfunc(*args):
|
||||
args = args[:i] + (backend.newp(BType, args[i]),) + args[i+1:]
|
||||
return oldfunc(*args)
|
||||
if i == "result":
|
||||
ffi = self.ffi
|
||||
def newfunc(*args):
|
||||
res = ffi.new(BType)
|
||||
oldfunc(res, *args)
|
||||
return res[0]
|
||||
else:
|
||||
def newfunc(*args):
|
||||
args = args[:i] + (backend.newp(BType, args[i]),) + args[i+1:]
|
||||
return oldfunc(*args)
|
||||
newfunc._cffi_base_type = base_tp
|
||||
return newfunc
|
||||
|
||||
|
|
@ -235,7 +266,8 @@ class VGenericEngine(object):
|
|||
prnt('static void %s(%s *p)' % (checkfuncname, cname))
|
||||
prnt('{')
|
||||
prnt(' /* only to generate compile-time warnings or errors */')
|
||||
for fname, ftype, fbitsize in tp.enumfields():
|
||||
prnt(' (void)p;')
|
||||
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||
if (isinstance(ftype, model.PrimitiveType)
|
||||
and ftype.is_integer_type()) or fbitsize >= 0:
|
||||
# accept all integers, but complain on float or double
|
||||
|
|
@ -244,7 +276,8 @@ class VGenericEngine(object):
|
|||
# only accept exactly the type declared.
|
||||
try:
|
||||
prnt(' { %s = &p->%s; (void)tmp; }' % (
|
||||
ftype.get_c_name('*tmp', 'field %r'%fname), fname))
|
||||
ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual),
|
||||
fname))
|
||||
except ffiplatform.VerificationError as e:
|
||||
prnt(' /* %s */' % str(e)) # cannot verify it, ignore
|
||||
prnt('}')
|
||||
|
|
@ -255,7 +288,7 @@ class VGenericEngine(object):
|
|||
prnt(' static intptr_t nums[] = {')
|
||||
prnt(' sizeof(%s),' % cname)
|
||||
prnt(' offsetof(struct _cffi_aligncheck, y),')
|
||||
for fname, ftype, fbitsize in tp.enumfields():
|
||||
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||
if fbitsize >= 0:
|
||||
continue # xxx ignore fbitsize for now
|
||||
prnt(' offsetof(%s, %s),' % (cname, fname))
|
||||
|
|
@ -317,7 +350,7 @@ class VGenericEngine(object):
|
|||
check(layout[0], ffi.sizeof(BStruct), "wrong total size")
|
||||
check(layout[1], ffi.alignof(BStruct), "wrong total alignment")
|
||||
i = 2
|
||||
for fname, ftype, fbitsize in tp.enumfields():
|
||||
for fname, ftype, fbitsize, fqual in tp.enumfields():
|
||||
if fbitsize >= 0:
|
||||
continue # xxx ignore fbitsize for now
|
||||
check(layout[i], ffi.offsetof(BStruct, fname),
|
||||
|
|
@ -354,11 +387,20 @@ class VGenericEngine(object):
|
|||
# ----------
|
||||
# constants, likely declared with '#define'
|
||||
|
||||
def _generate_gen_const(self, is_int, name, tp=None, category='const'):
|
||||
def _generate_gen_const(self, is_int, name, tp=None, category='const',
|
||||
check_value=None):
|
||||
prnt = self._prnt
|
||||
funcname = '_cffi_%s_%s' % (category, name)
|
||||
self.export_symbols.append(funcname)
|
||||
if is_int:
|
||||
if check_value is not None:
|
||||
assert is_int
|
||||
assert category == 'const'
|
||||
prnt('int %s(char *out_error)' % funcname)
|
||||
prnt('{')
|
||||
self._check_int_constant_value(name, check_value)
|
||||
prnt(' return 0;')
|
||||
prnt('}')
|
||||
elif is_int:
|
||||
assert category == 'const'
|
||||
prnt('int %s(long long *out_value)' % funcname)
|
||||
prnt('{')
|
||||
|
|
@ -367,12 +409,17 @@ class VGenericEngine(object):
|
|||
prnt('}')
|
||||
else:
|
||||
assert tp is not None
|
||||
prnt(tp.get_c_name(' %s(void)' % funcname, name),)
|
||||
prnt('{')
|
||||
assert check_value is None
|
||||
if category == 'var':
|
||||
ampersand = '&'
|
||||
else:
|
||||
ampersand = ''
|
||||
extra = ''
|
||||
if category == 'const' and isinstance(tp, model.StructOrUnion):
|
||||
extra = 'const *'
|
||||
ampersand = '&'
|
||||
prnt(tp.get_c_name(' %s%s(void)' % (extra, funcname), name))
|
||||
prnt('{')
|
||||
prnt(' return (%s%s);' % (ampersand, name))
|
||||
prnt('}')
|
||||
prnt()
|
||||
|
|
@ -383,9 +430,13 @@ class VGenericEngine(object):
|
|||
|
||||
_loading_gen_constant = _loaded_noop
|
||||
|
||||
def _load_constant(self, is_int, tp, name, module):
|
||||
def _load_constant(self, is_int, tp, name, module, check_value=None):
|
||||
funcname = '_cffi_const_%s' % name
|
||||
if is_int:
|
||||
if check_value is not None:
|
||||
assert is_int
|
||||
self._load_known_int_constant(module, funcname)
|
||||
value = check_value
|
||||
elif is_int:
|
||||
BType = self.ffi._typeof_locked("long long*")[0]
|
||||
BFunc = self.ffi._typeof_locked("int(*)(long long*)")[0]
|
||||
function = module.load_function(BFunc, funcname)
|
||||
|
|
@ -396,9 +447,15 @@ class VGenericEngine(object):
|
|||
BLongLong = self.ffi._typeof_locked("long long")[0]
|
||||
value += (1 << (8*self.ffi.sizeof(BLongLong)))
|
||||
else:
|
||||
BFunc = self.ffi._typeof_locked(tp.get_c_name('(*)(void)', name))[0]
|
||||
assert check_value is None
|
||||
fntypeextra = '(*)(void)'
|
||||
if isinstance(tp, model.StructOrUnion):
|
||||
fntypeextra = '*' + fntypeextra
|
||||
BFunc = self.ffi._typeof_locked(tp.get_c_name(fntypeextra, name))[0]
|
||||
function = module.load_function(BFunc, funcname)
|
||||
value = function()
|
||||
if isinstance(tp, model.StructOrUnion):
|
||||
value = value[0]
|
||||
return value
|
||||
|
||||
def _loaded_gen_constant(self, tp, name, module, library):
|
||||
|
|
@ -410,6 +467,36 @@ class VGenericEngine(object):
|
|||
# ----------
|
||||
# enums
|
||||
|
||||
def _check_int_constant_value(self, name, value):
|
||||
prnt = self._prnt
|
||||
if value <= 0:
|
||||
prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % (
|
||||
name, name, value))
|
||||
else:
|
||||
prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % (
|
||||
name, name, value))
|
||||
prnt(' char buf[64];')
|
||||
prnt(' if ((%s) <= 0)' % name)
|
||||
prnt(' sprintf(buf, "%%ld", (long)(%s));' % name)
|
||||
prnt(' else')
|
||||
prnt(' sprintf(buf, "%%lu", (unsigned long)(%s));' %
|
||||
name)
|
||||
prnt(' sprintf(out_error, "%s has the real value %s, not %s",')
|
||||
prnt(' "%s", buf, "%d");' % (name[:100], value))
|
||||
prnt(' return -1;')
|
||||
prnt(' }')
|
||||
|
||||
def _load_known_int_constant(self, module, funcname):
|
||||
BType = self.ffi._typeof_locked("char[]")[0]
|
||||
BFunc = self.ffi._typeof_locked("int(*)(char*)")[0]
|
||||
function = module.load_function(BFunc, funcname)
|
||||
p = self.ffi.new(BType, 256)
|
||||
if function(p) < 0:
|
||||
error = self.ffi.string(p)
|
||||
if sys.version_info >= (3,):
|
||||
error = str(error, 'utf-8')
|
||||
raise ffiplatform.VerificationError(error)
|
||||
|
||||
def _enum_funcname(self, prefix, name):
|
||||
# "$enum_$1" => "___D_enum____D_1"
|
||||
name = name.replace('$', '___D_')
|
||||
|
|
@ -427,24 +514,7 @@ class VGenericEngine(object):
|
|||
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) {' % (
|
||||
enumerator, enumerator, enumvalue))
|
||||
else:
|
||||
prnt(' if ((%s) < 0 || (unsigned long)(%s) != %dUL) {' % (
|
||||
enumerator, enumerator, enumvalue))
|
||||
prnt(' char buf[64];')
|
||||
prnt(' if ((%s) < 0)' % enumerator)
|
||||
prnt(' sprintf(buf, "%%ld", (long)(%s));' % enumerator)
|
||||
prnt(' else')
|
||||
prnt(' sprintf(buf, "%%lu", (unsigned long)(%s));' %
|
||||
enumerator)
|
||||
prnt(' sprintf(out_error,'
|
||||
' "%s has the real value %s, not %s",')
|
||||
prnt(' "%s", buf, "%d");' % (
|
||||
enumerator[:100], enumvalue))
|
||||
prnt(' return -1;')
|
||||
prnt(' }')
|
||||
self._check_int_constant_value(enumerator, enumvalue)
|
||||
prnt(' return 0;')
|
||||
prnt('}')
|
||||
prnt()
|
||||
|
|
@ -456,16 +526,8 @@ class VGenericEngine(object):
|
|||
tp.enumvalues = tuple(enumvalues)
|
||||
tp.partial_resolved = True
|
||||
else:
|
||||
BType = self.ffi._typeof_locked("char[]")[0]
|
||||
BFunc = self.ffi._typeof_locked("int(*)(char*)")[0]
|
||||
funcname = self._enum_funcname(prefix, name)
|
||||
function = module.load_function(BFunc, funcname)
|
||||
p = self.ffi.new(BType, 256)
|
||||
if function(p) < 0:
|
||||
error = self.ffi.string(p)
|
||||
if sys.version_info >= (3,):
|
||||
error = str(error, 'utf-8')
|
||||
raise ffiplatform.VerificationError(error)
|
||||
self._load_known_int_constant(module, funcname)
|
||||
|
||||
def _loaded_gen_enum(self, tp, name, module, library):
|
||||
for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
|
||||
|
|
@ -476,13 +538,21 @@ class VGenericEngine(object):
|
|||
# macros: for now only for integers
|
||||
|
||||
def _generate_gen_macro_decl(self, tp, name):
|
||||
assert tp == '...'
|
||||
self._generate_gen_const(True, name)
|
||||
if tp == '...':
|
||||
check_value = None
|
||||
else:
|
||||
check_value = tp # an integer
|
||||
self._generate_gen_const(True, name, check_value=check_value)
|
||||
|
||||
_loading_gen_macro = _loaded_noop
|
||||
|
||||
def _loaded_gen_macro(self, tp, name, module, library):
|
||||
value = self._load_constant(True, tp, name, module)
|
||||
if tp == '...':
|
||||
check_value = None
|
||||
else:
|
||||
check_value = tp # an integer
|
||||
value = self._load_constant(True, tp, name, module,
|
||||
check_value=check_value)
|
||||
setattr(library, name, value)
|
||||
type(library)._cffi_dir.append(name)
|
||||
|
||||
|
|
@ -565,6 +635,24 @@ cffimod_header = r'''
|
|||
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
|
||||
|
|
|
|||
|
|
@ -1,12 +1,47 @@
|
|||
import sys, os, binascii, imp, shutil
|
||||
from . import __version__
|
||||
import sys, os, binascii, shutil, io
|
||||
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]
|
||||
|
||||
|
||||
if sys.version_info >= (3,):
|
||||
NativeIO = io.StringIO
|
||||
else:
|
||||
class NativeIO(io.BytesIO):
|
||||
def write(self, s):
|
||||
if isinstance(s, unicode):
|
||||
s = s.encode('ascii')
|
||||
super(NativeIO, self).write(s)
|
||||
|
||||
def _hack_at_distutils():
|
||||
# Windows-only workaround for some configurations: see
|
||||
# https://bugs.python.org/issue23246 (Python 2.7 with
|
||||
# a specific MS compiler suite download)
|
||||
if sys.platform == "win32":
|
||||
try:
|
||||
import setuptools # for side-effects, patches distutils
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
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):
|
||||
if ffi._parser._uses_new_feature:
|
||||
raise ffiplatform.VerificationError(
|
||||
"feature not supported with ffi.verify(), but only "
|
||||
"with ffi.set_source(): %s" % (ffi._parser._uses_new_feature,))
|
||||
self.ffi = ffi
|
||||
self.preamble = preamble
|
||||
if not modulename:
|
||||
|
|
@ -14,14 +49,15 @@ class Verifier(object):
|
|||
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 +69,7 @@ class Verifier(object):
|
|||
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
|
||||
|
|
@ -86,6 +122,7 @@ class Verifier(object):
|
|||
return basename
|
||||
|
||||
def get_extension(self):
|
||||
_hack_at_distutils() # backward compatibility hack
|
||||
if not self._has_source:
|
||||
with self.ffi._lock:
|
||||
if not self._has_source:
|
||||
|
|
@ -97,6 +134,20 @@ class Verifier(object):
|
|||
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):
|
||||
|
|
@ -118,19 +169,36 @@ class Verifier(object):
|
|||
self._vengine.collect_types()
|
||||
self._has_module = True
|
||||
|
||||
def _write_source(self, file=None):
|
||||
must_close = (file is None)
|
||||
if must_close:
|
||||
_ensure_dir(self.sourcefilename)
|
||||
file = open(self.sourcefilename, 'w')
|
||||
def _write_source_to(self, file):
|
||||
self._vengine._f = file
|
||||
try:
|
||||
self._vengine.write_source_to_f()
|
||||
finally:
|
||||
del self._vengine._f
|
||||
if must_close:
|
||||
file.close()
|
||||
if must_close:
|
||||
|
||||
def _write_source(self, file=None):
|
||||
if file is not None:
|
||||
self._write_source_to(file)
|
||||
else:
|
||||
# Write our source file to an in memory file.
|
||||
f = NativeIO()
|
||||
self._write_source_to(f)
|
||||
source_data = f.getvalue()
|
||||
|
||||
# Determine if this matches the current file
|
||||
if os.path.exists(self.sourcefilename):
|
||||
with open(self.sourcefilename, "r") as fp:
|
||||
needs_written = not (fp.read() == source_data)
|
||||
else:
|
||||
needs_written = True
|
||||
|
||||
# Actually write the file out if it doesn't match
|
||||
if needs_written:
|
||||
_ensure_dir(self.sourcefilename)
|
||||
with open(self.sourcefilename, "w") as fp:
|
||||
fp.write(source_data)
|
||||
|
||||
# Set this flag
|
||||
self._has_source = True
|
||||
|
||||
def _compile_module(self):
|
||||
|
|
@ -148,7 +216,10 @@ class Verifier(object):
|
|||
|
||||
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 +252,9 @@ _TMPDIR = None
|
|||
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 +296,7 @@ def cleanup_tmpdir(tmpdir=None, keep_so=False):
|
|||
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':
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue