[pypy-commit] pypy cffi-1.0: Import cffi 1.0.0 (revision 8bb4a702b17d)
arigo
noreply at buildbot.pypy.org
Sat May 9 11:13:21 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r77241:a365f60463e9
Date: 2015-05-09 08:59 +0000
http://bitbucket.org/pypy/pypy/changeset/a365f60463e9/
Log: Import cffi 1.0.0 (revision 8bb4a702b17d)
diff too long, truncating to 2000 out of 7137 lines
diff --git a/lib_pypy/_cffi1/__init__.py b/lib_pypy/_cffi1/__init__.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_cffi1/__init__.py
@@ -0,0 +1,1 @@
+from .recompiler import make_c_source, recompile
diff --git a/lib_pypy/_cffi1/cffi_opcode.py b/lib_pypy/_cffi1/cffi_opcode.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_cffi1/cffi_opcode.py
@@ -0,0 +1,144 @@
+
+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, %d)' % (classname, self.arg)
+ def __str__(self):
+ classname = CLASS_NAME.get(self.op, self.op)
+ return '(%s %s)' % (classname, self.arg)
+
+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
+
+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
+
+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
+
+CLASS_NAME = {}
+for _name, _value in list(globals().items()):
+ if _name.startswith('OP_') and isinstance(_value, int):
+ CLASS_NAME[_value] = _name[3:]
diff --git a/lib_pypy/_cffi1/recompiler.py b/lib_pypy/_cffi1/recompiler.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_cffi1/recompiler.py
@@ -0,0 +1,906 @@
+import os, sys, io
+from cffi import ffiplatform, model
+from .cffi_opcode import *
+
+
+class Recompiler:
+
+ def __init__(self, ffi, module_name):
+ self.ffi = ffi
+ self.module_name = module_name
+
+ def collect_type_table(self):
+ self._typesdict = {}
+ self._generate("collecttype")
+ #
+ all_decls = sorted(self._typesdict, key=str)
+ #
+ # prepare all FUNCTION bytecode sequences first
+ self.cffi_types = []
+ for tp in all_decls:
+ if tp.is_raw_function:
+ assert self._typesdict[tp] is None
+ self._typesdict[tp] = len(self.cffi_types)
+ self.cffi_types.append(tp) # placeholder
+ for tp1 in tp.args:
+ assert isinstance(tp1, (model.VoidType,
+ model.PrimitiveType,
+ model.PointerType,
+ model.StructOrUnionOrEnum,
+ model.FunctionPtrType))
+ if self._typesdict[tp1] is None:
+ self._typesdict[tp1] = len(self.cffi_types)
+ self.cffi_types.append(tp1) # placeholder
+ self.cffi_types.append('END') # placeholder
+ #
+ # prepare all OTHER bytecode sequences
+ for tp in all_decls:
+ if not tp.is_raw_function and self._typesdict[tp] is None:
+ self._typesdict[tp] = len(self.cffi_types)
+ self.cffi_types.append(tp) # placeholder
+ if tp.is_array_type and tp.length is not None:
+ self.cffi_types.append('LEN') # placeholder
+ assert None not in self._typesdict.values()
+ #
+ # collect all structs and unions and enums
+ self._struct_unions = {}
+ self._enums = {}
+ for tp in all_decls:
+ if isinstance(tp, model.StructOrUnion):
+ self._struct_unions[tp] = None
+ elif isinstance(tp, model.EnumType):
+ self._enums[tp] = None
+ for i, tp in enumerate(sorted(self._struct_unions,
+ key=lambda tp: tp.name)):
+ self._struct_unions[tp] = i
+ for i, tp in enumerate(sorted(self._enums,
+ key=lambda tp: tp.name)):
+ self._enums[tp] = i
+ #
+ # emit all bytecode sequences now
+ for tp in all_decls:
+ method = getattr(self, '_emit_bytecode_' + tp.__class__.__name__)
+ method(tp, self._typesdict[tp])
+ #
+ # consistency check
+ for op in self.cffi_types:
+ assert isinstance(op, CffiOp)
+
+ def _do_collect_type(self, tp):
+ if not isinstance(tp, model.BaseTypeByIdentity):
+ if isinstance(tp, tuple):
+ for x in tp:
+ self._do_collect_type(x)
+ return
+ if tp not in self._typesdict:
+ self._typesdict[tp] = None
+ if isinstance(tp, model.FunctionPtrType):
+ self._do_collect_type(tp.as_raw_function())
+ elif isinstance(tp, model.StructOrUnion):
+ if tp.fldtypes is not None and (
+ tp not in self.ffi._parser._included_declarations):
+ for name1, tp1, _ in tp.enumfields():
+ self._do_collect_type(self._field_type(tp, name1, tp1))
+ else:
+ for _, x in tp._get_items():
+ self._do_collect_type(x)
+
+ def _get_declarations(self):
+ return sorted(self.ffi._parser._declarations.items())
+
+ def _generate(self, step_name):
+ for name, tp in self._get_declarations():
+ kind, realname = name.split(' ', 1)
+ try:
+ method = getattr(self, '_generate_cpy_%s_%s' % (kind,
+ step_name))
+ except AttributeError:
+ raise ffiplatform.VerificationError(
+ "not implemented in recompile(): %r" % name)
+ try:
+ method(tp, realname)
+ except Exception as e:
+ model.attach_exception_info(e, name)
+ raise
+
+ # ----------
+
+ def _prnt(self, what=''):
+ self._f.write(what + '\n')
+
+ def _gettypenum(self, type):
+ # a KeyError here is a bug. please report it! :-)
+ return self._typesdict[type]
+
+ def _rel_readlines(self, filename):
+ g = open(os.path.join(os.path.dirname(__file__), filename), 'r')
+ lines = g.readlines()
+ g.close()
+ return lines
+
+ def write_source_to_f(self, f, preamble):
+ self._f = f
+ prnt = self._prnt
+ #
+ # first the '#include' (actually done by inlining the file's content)
+ lines = self._rel_readlines('_cffi_include.h')
+ i = lines.index('#include "parse_c_type.h"\n')
+ lines[i:i+1] = self._rel_readlines('parse_c_type.h')
+ prnt(''.join(lines))
+ #
+ # then paste the C source given by the user, verbatim.
+ prnt('/************************************************************/')
+ prnt()
+ prnt(preamble)
+ prnt()
+ prnt('/************************************************************/')
+ prnt()
+ #
+ # the declaration of '_cffi_types'
+ prnt('static void *_cffi_types[] = {')
+ self.cffi_types = tuple(self.cffi_types) # don't change any more
+ typeindex2type = dict([(i, tp) for (tp, i) in self._typesdict.items()])
+ for i, op in enumerate(self.cffi_types):
+ comment = ''
+ if i in typeindex2type:
+ comment = ' // ' + typeindex2type[i]._get_c_name()
+ prnt('/* %2d */ %s,%s' % (i, op.as_c_expr(), comment))
+ if not self.cffi_types:
+ prnt(' 0')
+ prnt('};')
+ prnt()
+ #
+ # call generate_cpy_xxx_decl(), for every xxx found from
+ # ffi._parser._declarations. This generates all the functions.
+ self._seen_constants = set()
+ self._generate("decl")
+ #
+ # the declaration of '_cffi_globals' and '_cffi_typenames'
+ ALL_STEPS = ["global", "field", "struct_union", "enum", "typename"]
+ nums = {}
+ self._lsts = {}
+ for step_name in ALL_STEPS:
+ self._lsts[step_name] = []
+ self._seen_struct_unions = set()
+ self._generate("ctx")
+ self._add_missing_struct_unions()
+ for step_name in ALL_STEPS:
+ lst = self._lsts[step_name]
+ nums[step_name] = len(lst)
+ if nums[step_name] > 0:
+ lst.sort() # sort by name, which is at the start of each line
+ prnt('static const struct _cffi_%s_s _cffi_%ss[] = {' % (
+ step_name, step_name))
+ if step_name == 'field':
+ self._fix_final_field_list(lst)
+ for line in lst:
+ prnt(line)
+ if all(line.startswith('#') for line in lst):
+ prnt(' { 0 }')
+ prnt('};')
+ prnt()
+ #
+ # check for a possible internal inconsistency: _cffi_struct_unions
+ # should have been generated with exactly self._struct_unions
+ lst = self._lsts["struct_union"]
+ for tp, i in self._struct_unions.items():
+ assert i < len(lst)
+ assert lst[i].startswith(' { "%s"' % tp.name)
+ assert len(lst) == len(self._struct_unions)
+ # same with enums
+ lst = self._lsts["enum"]
+ for tp, i in self._enums.items():
+ assert i < len(lst)
+ assert lst[i].startswith(' { "%s"' % tp.name)
+ assert len(lst) == len(self._enums)
+ #
+ # the declaration of '_cffi_includes'
+ if self.ffi._included_ffis:
+ prnt('static const char * const _cffi_includes[] = {')
+ for ffi_to_include in self.ffi._included_ffis:
+ if not hasattr(ffi_to_include, '_recompiler_module_name'):
+ raise ffiplatform.VerificationError(
+ "this ffi includes %r, but the latter has not been "
+ "turned into a C module" % (ffi_to_include,))
+ prnt(' "%s",' % (ffi_to_include._recompiler_module_name,))
+ prnt(' NULL')
+ prnt('};')
+ prnt()
+ #
+ # the declaration of '_cffi_type_context'
+ prnt('static const struct _cffi_type_context_s _cffi_type_context = {')
+ prnt(' _cffi_types,')
+ for step_name in ALL_STEPS:
+ if nums[step_name] > 0:
+ prnt(' _cffi_%ss,' % step_name)
+ else:
+ prnt(' NULL, /* no %ss */' % step_name)
+ for step_name in ALL_STEPS:
+ if step_name != "field":
+ prnt(' %d, /* num_%ss */' % (nums[step_name], step_name))
+ if self.ffi._included_ffis:
+ prnt(' _cffi_includes,')
+ else:
+ prnt(' NULL, /* no includes */')
+ prnt(' %d, /* num_types */' % (len(self.cffi_types),))
+ prnt(' 0, /* flags */')
+ prnt('};')
+ prnt()
+ #
+ # the init function, loading _cffi_backend and calling a method there
+ base_module_name = self.module_name.split('.')[-1]
+ prnt('#ifdef PYPY_VERSION')
+ prnt('PyMODINIT_FUNC')
+ prnt('_cffi_pypyinit_%s(const void *p[])' % (base_module_name,))
+ prnt('{')
+ prnt(' p[0] = (const void *)0x10000f0;')
+ prnt(' p[1] = &_cffi_type_context;')
+ prnt('}')
+ prnt('#elif PY_MAJOR_VERSION >= 3')
+ prnt('PyMODINIT_FUNC')
+ prnt('PyInit_%s(void)' % (base_module_name,))
+ prnt('{')
+ prnt(' if (_cffi_init() < 0)')
+ prnt(' return NULL;')
+ prnt(' return _cffi_init_module("%s", &_cffi_type_context);' % (
+ self.module_name,))
+ prnt('}')
+ prnt('#else')
+ prnt('PyMODINIT_FUNC')
+ prnt('init%s(void)' % (base_module_name,))
+ prnt('{')
+ prnt(' if (_cffi_init() < 0)')
+ prnt(' return;')
+ prnt(' _cffi_init_module("%s", &_cffi_type_context);' % (
+ self.module_name,))
+ prnt('}')
+ prnt('#endif')
+ self.ffi._recompiler_module_name = self.module_name
+
+ # ----------
+
+ def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode):
+ extraarg = ''
+ if isinstance(tp, model.PrimitiveType):
+ if tp.is_integer_type() and tp.name != '_Bool':
+ converter = '_cffi_to_c_int'
+ extraarg = ', %s' % tp.name
+ else:
+ converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''),
+ tp.name.replace(' ', '_'))
+ errvalue = '-1'
+ #
+ elif isinstance(tp, model.PointerType):
+ self._convert_funcarg_to_c_ptr_or_array(tp, fromvar,
+ tovar, errcode)
+ return
+ #
+ elif isinstance(tp, (model.StructOrUnion, model.EnumType)):
+ # a struct (not a struct pointer) as a function argument
+ self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)'
+ % (tovar, self._gettypenum(tp), fromvar))
+ self._prnt(' %s;' % errcode)
+ return
+ #
+ elif isinstance(tp, model.FunctionPtrType):
+ converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('')
+ extraarg = ', _cffi_type(%d)' % self._gettypenum(tp)
+ errvalue = 'NULL'
+ #
+ else:
+ raise NotImplementedError(tp)
+ #
+ self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg))
+ self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % (
+ tovar, tp.get_c_name(''), errvalue))
+ self._prnt(' %s;' % errcode)
+
+ def _extra_local_variables(self, tp, localvars):
+ if isinstance(tp, model.PointerType):
+ localvars.add('Py_ssize_t datasize')
+
+ def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode):
+ self._prnt(' datasize = _cffi_prepare_pointer_call_argument(')
+ self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % (
+ self._gettypenum(tp), fromvar, tovar))
+ self._prnt(' if (datasize != 0) {')
+ self._prnt(' if (datasize < 0)')
+ self._prnt(' %s;' % errcode)
+ 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))
+ self._prnt(' %s;' % errcode)
+ self._prnt(' }')
+
+ def _convert_expr_from_c(self, tp, var, context):
+ if isinstance(tp, model.PrimitiveType):
+ if tp.is_integer_type():
+ return '_cffi_from_c_int(%s, %s)' % (var, tp.name)
+ elif tp.name != 'long double':
+ return '_cffi_from_c_%s(%s)' % (tp.name.replace(' ', '_'), var)
+ else:
+ return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % (
+ var, self._gettypenum(tp))
+ elif isinstance(tp, (model.PointerType, model.FunctionPtrType)):
+ return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % (
+ var, self._gettypenum(tp))
+ elif isinstance(tp, model.ArrayType):
+ return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % (
+ var, self._gettypenum(model.PointerType(tp.item)))
+ elif isinstance(tp, model.StructType):
+ if tp.fldnames is None:
+ raise TypeError("'%s' is used as %s, but is opaque" % (
+ tp._get_c_name(), context))
+ return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % (
+ var, self._gettypenum(tp))
+ elif isinstance(tp, model.EnumType):
+ return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % (
+ var, self._gettypenum(tp))
+ else:
+ raise NotImplementedError(tp)
+
+ # ----------
+ # typedefs
+
+ def _generate_cpy_typedef_collecttype(self, tp, name):
+ self._do_collect_type(tp)
+
+ def _generate_cpy_typedef_decl(self, tp, name):
+ pass
+
+ def _typedef_ctx(self, tp, name):
+ type_index = self._typesdict[tp]
+ self._lsts["typename"].append(
+ ' { "%s", %d },' % (name, type_index))
+
+ def _generate_cpy_typedef_ctx(self, tp, name):
+ self._typedef_ctx(tp, name)
+ if getattr(tp, "origin", None) == "unknown_type":
+ self._struct_ctx(tp, tp.name, approxname=None)
+ elif isinstance(tp, model.NamedPointerType):
+ self._struct_ctx(tp.totype, tp.totype.name, approxname=None)
+
+ # ----------
+ # function declarations
+
+ def _generate_cpy_function_collecttype(self, tp, name):
+ self._do_collect_type(tp.as_raw_function())
+ if tp.ellipsis:
+ self._do_collect_type(tp)
+
+ def _generate_cpy_function_decl(self, tp, name):
+ assert isinstance(tp, model.FunctionPtrType)
+ if tp.ellipsis:
+ # cannot support vararg functions better than this: check for its
+ # exact type (including the fixed arguments), and build it as a
+ # constant function pointer (no CPython wrapper)
+ self._generate_cpy_constant_decl(tp, name)
+ return
+ prnt = self._prnt
+ numargs = len(tp.args)
+ if numargs == 0:
+ argname = 'noarg'
+ elif numargs == 1:
+ argname = 'arg0'
+ else:
+ argname = 'args'
+ prnt('#ifndef PYPY_VERSION') # ------------------------------
+ prnt('static PyObject *')
+ prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname))
+ prnt('{')
+ #
+ context = 'argument of %s' % name
+ arguments = []
+ for i, type in enumerate(tp.args):
+ arg = type.get_c_name(' x%d' % i, context)
+ arguments.append(arg)
+ prnt(' %s;' % arg)
+ #
+ localvars = set()
+ for type in tp.args:
+ self._extra_local_variables(type, localvars)
+ for decl in localvars:
+ prnt(' %s;' % (decl,))
+ #
+ if not isinstance(tp.result, model.VoidType):
+ result_code = 'result = '
+ context = 'result of %s' % name
+ result_decl = ' %s;' % tp.result.get_c_name(' result', context)
+ prnt(result_decl)
+ else:
+ result_decl = None
+ result_code = ''
+ #
+ if len(tp.args) > 1:
+ rng = range(len(tp.args))
+ for i in rng:
+ prnt(' PyObject *arg%d;' % i)
+ prnt()
+ prnt(' if (!PyArg_ParseTuple(args, "%s:%s", %s))' % (
+ 'O' * numargs, name, ', '.join(['&arg%d' % i for i in rng])))
+ prnt(' return NULL;')
+ prnt()
+ #
+ for i, type in enumerate(tp.args):
+ self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i,
+ 'return NULL')
+ prnt()
+ #
+ prnt(' Py_BEGIN_ALLOW_THREADS')
+ prnt(' _cffi_restore_errno();')
+ call_arguments = ['x%d' % i for i in range(len(tp.args))]
+ call_arguments = ', '.join(call_arguments)
+ call_code = ' { %s%s(%s); }' % (result_code, name, call_arguments)
+ prnt(call_code)
+ prnt(' _cffi_save_errno();')
+ 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'))
+ else:
+ prnt(' Py_INCREF(Py_None);')
+ prnt(' return Py_None;')
+ prnt('}')
+ prnt('#else') # ------------------------------
+ repr_arguments = ', '.join(arguments)
+ repr_arguments = repr_arguments or 'void'
+ name_and_arguments = '_cffi_f_%s(%s)' % (name, repr_arguments)
+ prnt('static %s' % (tp.result.get_c_name(name_and_arguments),))
+ prnt('{')
+ if result_decl:
+ prnt(result_decl)
+ prnt(call_code)
+ if result_decl:
+ prnt(' return result;')
+ prnt('}')
+ prnt('#endif') # ------------------------------
+ prnt()
+
+ def _generate_cpy_function_ctx(self, tp, name):
+ if tp.ellipsis:
+ self._generate_cpy_constant_ctx(tp, name)
+ return
+ type_index = self._typesdict[tp.as_raw_function()]
+ numargs = len(tp.args)
+ if numargs == 0:
+ meth_kind = 'N' # 'METH_NOARGS'
+ elif numargs == 1:
+ meth_kind = 'O' # 'METH_O'
+ else:
+ meth_kind = 'V' # 'METH_VARARGS'
+ self._lsts["global"].append(
+ ' { "%s", _cffi_f_%s, _CFFI_OP(_CFFI_OP_CPYTHON_BLTN_%s, %d), 0 },'
+ % (name, name, meth_kind, type_index))
+
+ # ----------
+ # named structs or unions
+
+ def _field_type(self, tp_struct, field_name, tp_field):
+ if isinstance(tp_field, model.ArrayType) and tp_field.length == '...':
+ ptr_struct_name = tp_struct.get_c_name('*')
+ actual_length = '_cffi_array_len(((%s)0)->%s)' % (
+ ptr_struct_name, field_name)
+ tp_field = tp_field.resolve_length(actual_length)
+ return tp_field
+
+ def _struct_collecttype(self, tp):
+ self._do_collect_type(tp)
+
+ def _struct_decl(self, tp, cname, approxname):
+ if tp.fldtypes is None:
+ return
+ prnt = self._prnt
+ checkfuncname = '_cffi_checkfld_%s' % (approxname,)
+ prnt('_CFFI_UNUSED_FN')
+ prnt('static void %s(%s *p)' % (checkfuncname, cname))
+ prnt('{')
+ prnt(' /* only to generate compile-time warnings or errors */')
+ prnt(' (void)p;')
+ for fname, ftype, fbitsize in tp.enumfields():
+ if (isinstance(ftype, model.PrimitiveType)
+ and ftype.is_integer_type()) or fbitsize >= 0:
+ # accept all integers, but complain on float or double
+ prnt(' (void)((p->%s) << 1);' % fname)
+ else:
+ # only accept exactly the type declared.
+ try:
+ prnt(' { %s = &p->%s; (void)tmp; }' % (
+ ftype.get_c_name('*tmp', 'field %r'%fname), fname))
+ except ffiplatform.VerificationError as e:
+ prnt(' /* %s */' % str(e)) # cannot verify it, ignore
+ prnt('}')
+ prnt('struct _cffi_align_%s { char x; %s y; };' % (approxname, cname))
+ prnt()
+
+ def _struct_ctx(self, tp, cname, approxname):
+ type_index = self._typesdict[tp]
+ reason_for_not_expanding = None
+ flags = []
+ if isinstance(tp, model.UnionType):
+ flags.append("_CFFI_F_UNION")
+ if tp not in self.ffi._parser._included_declarations:
+ if tp.fldtypes is None:
+ reason_for_not_expanding = "opaque"
+ elif tp.partial or tp.has_anonymous_struct_fields():
+ pass # field layout obtained silently from the C compiler
+ else:
+ flags.append("_CFFI_F_CHECK_FIELDS")
+ if tp.packed:
+ flags.append("_CFFI_F_PACKED")
+ else:
+ flags.append("_CFFI_F_EXTERNAL")
+ reason_for_not_expanding = "external"
+ flags = '|'.join(flags) or '0'
+ if reason_for_not_expanding is None:
+ c_field = [approxname]
+ enumfields = list(tp.enumfields())
+ for fldname, fldtype, fbitsize in enumfields:
+ fldtype = self._field_type(tp, fldname, fldtype)
+ spaces = " " * len(fldname)
+ # cname is None for _add_missing_struct_unions() only
+ op = '_CFFI_OP_NOOP'
+ if fbitsize >= 0:
+ op = '_CFFI_OP_BITFIELD'
+ size = '%d /* bits */' % fbitsize
+ elif cname is None or (
+ isinstance(fldtype, model.ArrayType) and
+ fldtype.length is None):
+ size = '(size_t)-1'
+ else:
+ size = 'sizeof(((%s)0)->%s)' % (tp.get_c_name('*'), fldname)
+ if cname is None or fbitsize >= 0:
+ offset = '(size_t)-1'
+ else:
+ offset = 'offsetof(%s, %s)' % (tp.get_c_name(''), fldname)
+ c_field.append(
+ ' { "%s", %s,\n' % (fldname, offset) +
+ ' %s %s,\n' % (spaces, size) +
+ ' %s _CFFI_OP(%s, %s) },' % (
+ spaces, op, self._typesdict[fldtype]))
+ self._lsts["field"].append('\n'.join(c_field))
+ #
+ if cname is None: # unknown name, for _add_missing_struct_unions
+ size_align = (' (size_t)-2, -2, /* unnamed */\n' +
+ ' _cffi_FIELDS_FOR_%s, %d },' % (approxname,
+ len(enumfields),))
+ else:
+ size_align = ('\n' +
+ ' sizeof(%s),\n' % (cname,) +
+ ' offsetof(struct _cffi_align_%s, y),\n'% (approxname,) +
+ ' _cffi_FIELDS_FOR_%s, %d },' % (approxname,
+ len(enumfields),))
+ else:
+ size_align = ' (size_t)-1, -1, -1, 0 /* %s */ },' % (
+ reason_for_not_expanding,)
+ self._lsts["struct_union"].append(
+ ' { "%s", %d, %s,' % (tp.name, type_index, flags) + size_align)
+ self._seen_struct_unions.add(tp)
+
+ def _add_missing_struct_unions(self):
+ # not very nice, but some struct declarations might be missing
+ # because they don't have any known C name. Check that they are
+ # not partial (we can't complete or verify them!) and emit them
+ # anonymously.
+ for tp in list(self._struct_unions):
+ if tp not in self._seen_struct_unions:
+ if tp.partial:
+ raise NotImplementedError("internal inconsistency: %r is "
+ "partial but was not seen at "
+ "this point" % (tp,))
+ if tp.name.startswith('$') and tp.name[1:].isdigit():
+ approxname = tp.name[1:]
+ elif tp.name == '_IO_FILE' and tp.forcename == 'FILE':
+ approxname = 'FILE'
+ self._typedef_ctx(tp, 'FILE')
+ else:
+ raise NotImplementedError("internal inconsistency: %r" %
+ (tp,))
+ self._struct_ctx(tp, None, approxname)
+
+ def _fix_final_field_list(self, lst):
+ count = 0
+ for i in range(len(lst)):
+ struct_fields = lst[i]
+ pname = struct_fields.split('\n')[0]
+ define_macro = '#define _cffi_FIELDS_FOR_%s %d' % (pname, count)
+ lst[i] = define_macro + struct_fields[len(pname):]
+ count += lst[i].count('\n { "')
+
+ def _generate_cpy_struct_collecttype(self, tp, name):
+ self._struct_collecttype(tp)
+ _generate_cpy_union_collecttype = _generate_cpy_struct_collecttype
+
+ def _struct_names(self, tp):
+ cname = tp.get_c_name('')
+ if ' ' in cname:
+ return cname, cname.replace(' ', '_')
+ else:
+ return cname, '_' + cname
+
+ def _generate_cpy_struct_decl(self, tp, name):
+ self._struct_decl(tp, *self._struct_names(tp))
+ _generate_cpy_union_decl = _generate_cpy_struct_decl
+
+ def _generate_cpy_struct_ctx(self, tp, name):
+ self._struct_ctx(tp, *self._struct_names(tp))
+ _generate_cpy_union_ctx = _generate_cpy_struct_ctx
+
+ # ----------
+ # 'anonymous' declarations. These are produced for anonymous structs
+ # or unions; the 'name' is obtained by a typedef.
+
+ def _generate_cpy_anonymous_collecttype(self, tp, name):
+ if isinstance(tp, model.EnumType):
+ self._generate_cpy_enum_collecttype(tp, name)
+ else:
+ self._struct_collecttype(tp)
+
+ def _generate_cpy_anonymous_decl(self, tp, name):
+ if isinstance(tp, model.EnumType):
+ self._generate_cpy_enum_decl(tp)
+ else:
+ self._struct_decl(tp, name, 'typedef_' + name)
+
+ def _generate_cpy_anonymous_ctx(self, tp, name):
+ if isinstance(tp, model.EnumType):
+ self._enum_ctx(tp, name)
+ else:
+ self._struct_ctx(tp, name, 'typedef_' + name)
+
+ # ----------
+ # constants, declared with "static const ..."
+
+ def _generate_cpy_const(self, is_int, name, tp=None, category='const',
+ check_value=None):
+ if (category, name) in self._seen_constants:
+ raise ffiplatform.VerificationError(
+ "duplicate declaration of %s '%s'" % (category, name))
+ self._seen_constants.add((category, name))
+ #
+ prnt = self._prnt
+ funcname = '_cffi_%s_%s' % (category, name)
+ if is_int:
+ prnt('static int %s(unsigned long long *o)' % funcname)
+ prnt('{')
+ prnt(' int n = (%s) <= 0;' % (name,))
+ prnt(' *o = (unsigned long long)((%s) << 0);'
+ ' /* check that we get an integer */' % (name,))
+ if check_value is not None:
+ if check_value > 0:
+ check_value = '%dU' % (check_value,)
+ prnt(' if (!_cffi_check_int(*o, n, %s))' % (check_value,))
+ prnt(' n |= 2;')
+ prnt(' return n;')
+ prnt('}')
+ else:
+ assert check_value is None
+ prnt('static void %s(char *o)' % funcname)
+ prnt('{')
+ prnt(' *(%s)o = %s;' % (tp.get_c_name('*'), name))
+ prnt('}')
+ prnt()
+
+ def _generate_cpy_constant_collecttype(self, tp, name):
+ is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
+ if not is_int:
+ self._do_collect_type(tp)
+
+ def _generate_cpy_constant_decl(self, tp, name):
+ is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
+ self._generate_cpy_const(is_int, name, tp)
+
+ def _generate_cpy_constant_ctx(self, tp, name):
+ if isinstance(tp, model.PrimitiveType) and tp.is_integer_type():
+ type_op = '_CFFI_OP(_CFFI_OP_CONSTANT_INT, 0)'
+ else:
+ type_index = self._typesdict[tp]
+ type_op = '_CFFI_OP(_CFFI_OP_CONSTANT, %d)' % type_index
+ self._lsts["global"].append(
+ ' { "%s", _cffi_const_%s, %s, 0 },' % (name, name, type_op))
+
+ # ----------
+ # enums
+
+ def _generate_cpy_enum_collecttype(self, tp, name):
+ self._do_collect_type(tp)
+
+ def _generate_cpy_enum_decl(self, tp, name=None):
+ for enumerator in tp.enumerators:
+ self._generate_cpy_const(True, enumerator)
+
+ def _enum_ctx(self, tp, cname):
+ type_index = self._typesdict[tp]
+ type_op = '_CFFI_OP(_CFFI_OP_ENUM, -1)'
+ for enumerator in tp.enumerators:
+ self._lsts["global"].append(
+ ' { "%s", _cffi_const_%s, %s, 0 },' %
+ (enumerator, enumerator, type_op))
+ #
+ if cname is not None and '$' not in cname:
+ size = "sizeof(%s)" % cname
+ signed = "((%s)-1) <= 0" % cname
+ else:
+ basetp = tp.build_baseinttype(self.ffi, [])
+ size = self.ffi.sizeof(basetp)
+ signed = int(int(self.ffi.cast(basetp, -1)) < 0)
+ allenums = ",".join(tp.enumerators)
+ self._lsts["enum"].append(
+ ' { "%s", %d, _cffi_prim_int(%s, %s),\n'
+ ' "%s" },' % (tp.name, type_index, size, signed, allenums))
+
+ def _generate_cpy_enum_ctx(self, tp, name):
+ self._enum_ctx(tp, tp._get_c_name())
+
+ # ----------
+ # macros: for now only for integers
+
+ def _generate_cpy_macro_collecttype(self, tp, name):
+ pass
+
+ def _generate_cpy_macro_decl(self, tp, name):
+ if tp == '...':
+ check_value = None
+ else:
+ check_value = tp # an integer
+ self._generate_cpy_const(True, name, check_value=check_value)
+
+ def _generate_cpy_macro_ctx(self, tp, name):
+ self._lsts["global"].append(
+ ' { "%s", _cffi_const_%s,'
+ ' _CFFI_OP(_CFFI_OP_CONSTANT_INT, 0), 0 },' % (name, name))
+
+ # ----------
+ # global variables
+
+ def _global_type(self, tp, global_name):
+ if isinstance(tp, model.ArrayType) and tp.length == '...':
+ actual_length = '_cffi_array_len(%s)' % (global_name,)
+ tp = tp.resolve_length(actual_length)
+ return tp
+
+ def _generate_cpy_variable_collecttype(self, tp, name):
+ self._do_collect_type(self._global_type(tp, name))
+
+ def _generate_cpy_variable_decl(self, tp, name):
+ pass
+
+ def _generate_cpy_variable_ctx(self, tp, name):
+ tp = self._global_type(tp, name)
+ type_index = self._typesdict[tp]
+ if tp.sizeof_enabled():
+ size = "sizeof(%s)" % (name,)
+ else:
+ size = "0"
+ self._lsts["global"].append(
+ ' { "%s", &%s, _CFFI_OP(_CFFI_OP_GLOBAL_VAR, %d), %s },'
+ % (name, name, type_index, size))
+
+ # ----------
+ # emitting the opcodes for individual types
+
+ def _emit_bytecode_VoidType(self, tp, index):
+ self.cffi_types[index] = CffiOp(OP_PRIMITIVE, PRIM_VOID)
+
+ def _emit_bytecode_PrimitiveType(self, tp, index):
+ prim_index = PRIMITIVE_TO_INDEX[tp.name]
+ self.cffi_types[index] = CffiOp(OP_PRIMITIVE, prim_index)
+
+ def _emit_bytecode_RawFunctionType(self, tp, index):
+ self.cffi_types[index] = CffiOp(OP_FUNCTION, self._typesdict[tp.result])
+ index += 1
+ for tp1 in tp.args:
+ realindex = self._typesdict[tp1]
+ if index != realindex:
+ if isinstance(tp1, model.PrimitiveType):
+ self._emit_bytecode_PrimitiveType(tp1, index)
+ else:
+ self.cffi_types[index] = CffiOp(OP_NOOP, realindex)
+ index += 1
+ self.cffi_types[index] = CffiOp(OP_FUNCTION_END, int(tp.ellipsis))
+
+ def _emit_bytecode_PointerType(self, tp, index):
+ self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[tp.totype])
+
+ _emit_bytecode_ConstPointerType = _emit_bytecode_PointerType
+ _emit_bytecode_NamedPointerType = _emit_bytecode_PointerType
+
+ def _emit_bytecode_FunctionPtrType(self, tp, index):
+ raw = tp.as_raw_function()
+ self.cffi_types[index] = CffiOp(OP_POINTER, self._typesdict[raw])
+
+ def _emit_bytecode_ArrayType(self, tp, index):
+ item_index = self._typesdict[tp.item]
+ if tp.length is None:
+ self.cffi_types[index] = CffiOp(OP_OPEN_ARRAY, item_index)
+ elif tp.length == '...':
+ raise ffiplatform.VerificationError(
+ "type %s badly placed: the '...' array length can only be "
+ "used on global arrays or on fields of structures" % (
+ str(tp).replace('/*...*/', '...'),))
+ else:
+ assert self.cffi_types[index + 1] == 'LEN'
+ self.cffi_types[index] = CffiOp(OP_ARRAY, item_index)
+ self.cffi_types[index + 1] = CffiOp(None, str(tp.length))
+
+ def _emit_bytecode_StructType(self, tp, index):
+ struct_index = self._struct_unions[tp]
+ self.cffi_types[index] = CffiOp(OP_STRUCT_UNION, struct_index)
+ _emit_bytecode_UnionType = _emit_bytecode_StructType
+
+ def _emit_bytecode_EnumType(self, tp, index):
+ enum_index = self._enums[tp]
+ self.cffi_types[index] = CffiOp(OP_ENUM, enum_index)
+
+
+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 make_c_source(ffi, module_name, preamble, target_c_file):
+ recompiler = Recompiler(ffi, module_name)
+ recompiler.collect_type_table()
+ f = NativeIO()
+ recompiler.write_source_to_f(f, preamble)
+ output = f.getvalue()
+ try:
+ with open(target_c_file, 'r') as f1:
+ if f1.read(len(output) + 1) != output:
+ raise IOError
+ return False # already up-to-date
+ except IOError:
+ with open(target_c_file, 'w') as f1:
+ f1.write(output)
+ return True
+
+def _get_extension(module_name, c_file, kwds):
+ source_name = ffiplatform.maybe_relative_path(c_file)
+ return ffiplatform.get_extension(source_name, module_name, **kwds)
+
+def recompile(ffi, module_name, preamble, tmpdir='.',
+ call_c_compiler=True, c_file=None, **kwds):
+ if not isinstance(module_name, str):
+ module_name = module_name.encode('ascii')
+ if ffi._windows_unicode:
+ ffi._apply_windows_unicode(kwds)
+ if c_file is None:
+ c_file = os.path.join(tmpdir, module_name + '.c')
+ ext = _get_extension(module_name, c_file, kwds)
+ updated = make_c_source(ffi, module_name, preamble, c_file)
+ if call_c_compiler:
+ outputfilename = ffiplatform.compile(tmpdir, ext)
+ return outputfilename
+ else:
+ return ext, updated
+
+def verify(ffi, module_name, preamble, *args, **kwds):
+ from _cffi1.udir import udir
+ import imp
+ assert module_name not in sys.modules, "module name conflict: %r" % (
+ module_name,)
+ kwds.setdefault('tmpdir', str(udir))
+ outputfilename = recompile(ffi, module_name, preamble, *args, **kwds)
+ module = imp.load_dynamic(module_name, outputfilename)
+ #
+ # hack hack hack: copy all *bound methods* from module.ffi back to the
+ # ffi instance. Then calls like ffi.new() will invoke module.ffi.new().
+ for name in dir(module.ffi):
+ if not name.startswith('_'):
+ attr = getattr(module.ffi, name)
+ if attr is not getattr(ffi, name, object()):
+ setattr(ffi, name, attr)
+ def typeof_disabled(*args, **kwds):
+ raise NotImplementedError
+ ffi._typeof = typeof_disabled
+ return module.lib
diff --git a/lib_pypy/_cffi1/setup.py b/lib_pypy/_cffi1/setup.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_cffi1/setup.py
@@ -0,0 +1,6 @@
+from distutils.core import setup
+from distutils.extension import Extension
+setup(name='realize_c_type',
+ ext_modules=[Extension(name='realize_c_type',
+ sources=['realize_c_type.c',
+ 'parse_c_type.c'])])
diff --git a/lib_pypy/_cffi1/setup_manual.py b/lib_pypy/_cffi1/setup_manual.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_cffi1/setup_manual.py
@@ -0,0 +1,5 @@
+from distutils.core import setup
+from distutils.extension import Extension
+setup(name='manual',
+ ext_modules=[Extension(name='manual',
+ sources=['manual.c'])])
diff --git a/lib_pypy/_cffi1/setuptools_ext.py b/lib_pypy/_cffi1/setuptools_ext.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_cffi1/setuptools_ext.py
@@ -0,0 +1,80 @@
+try:
+ basestring
+except NameError:
+ # Python 3.x
+ basestring = str
+
+def error(msg):
+ from distutils.errors import DistutilsSetupError
+ raise DistutilsSetupError(msg)
+
+
+def add_cffi_module(dist, mod_spec):
+ import os
+ from cffi.api import FFI
+ from _cffi1 import recompiler
+ from distutils.core import Extension
+ from distutils.command.build_ext import build_ext
+ from distutils.dir_util import mkpath
+ from distutils import log
+
+ 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_mod_name, ffi_var_name = mod_spec.split(':')
+ except ValueError:
+ error("%r must be of the form 'build_mod_name:ffi_variable'" %
+ (mod_spec,))
+ mod = __import__(build_mod_name, None, None, [ffi_var_name])
+ try:
+ ffi = getattr(mod, ffi_var_name)
+ except AttributeError:
+ error("%r: object %r not found in module" % (mod_spec,
+ ffi_var_name))
+ 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 = ffi._recompiler_module_name
+ source, kwds = ffi._assigned_source
+ if ffi._windows_unicode:
+ kwds = kwds.copy()
+ ffi._apply_windows_unicode(kwds)
+
+ allsources = ['$PLACEHOLDER']
+ allsources.extend(kwds.get('sources', []))
+ ext = Extension(name=module_name, sources=allsources, **kwds)
+
+ def make_mod(tmpdir):
+ file_name = module_name + '.c'
+ log.info("generating cffi module %r" % file_name)
+ mkpath(tmpdir)
+ c_file = os.path.join(tmpdir, file_name)
+ 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':
+ ext.sources[0] = make_mod(self.build_temp)
+ base_class.run(self)
+ 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)
diff --git a/lib_pypy/_cffi1/support.py b/lib_pypy/_cffi1/support.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_cffi1/support.py
@@ -0,0 +1,19 @@
+import sys
+
+if sys.version_info < (3,):
+ __all__ = ['u']
+
+ class U(object):
+ def __add__(self, other):
+ return eval('u'+repr(other).replace(r'\\u', r'\u')
+ .replace(r'\\U', r'\U'))
+ u = U()
+ assert u+'a\x00b' == eval(r"u'a\x00b'")
+ assert u+'a\u1234b' == eval(r"u'a\u1234b'")
+ assert u+'a\U00012345b' == eval(r"u'a\U00012345b'")
+
+else:
+ __all__ = ['u', 'unicode', 'long']
+ u = ""
+ unicode = str
+ long = int
diff --git a/lib_pypy/_cffi1/test_cffi_binary.py b/lib_pypy/_cffi1/test_cffi_binary.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_cffi1/test_cffi_binary.py
@@ -0,0 +1,18 @@
+import py, sys, os
+import _cffi_backend
+
+def test_no_unknown_exported_symbols():
+ if not sys.platform.startswith('linux'):
+ py.test.skip("linux-only")
+ g = os.popen("objdump -T '%s'" % _cffi_backend.__file__, 'r')
+ for line in g:
+ if not line.startswith('0'):
+ continue
+ if '*UND*' in line:
+ continue
+ name = line.split()[-1]
+ if name.startswith('_') or name.startswith('.'):
+ continue
+ if name not in ('init_cffi_backend', 'PyInit__cffi_backend'):
+ raise Exception("Unexpected exported name %r" % (name,))
+ g.close()
diff --git a/lib_pypy/_cffi1/test_dlopen.py b/lib_pypy/_cffi1/test_dlopen.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_cffi1/test_dlopen.py
@@ -0,0 +1,57 @@
+import py
+py.test.skip("later")
+
+from cffi1 import FFI
+import math
+
+
+def test_cdef_struct():
+ ffi = FFI()
+ ffi.cdef("struct foo_s { int a, b; };")
+ assert ffi.sizeof("struct foo_s") == 8
+
+def test_cdef_union():
+ ffi = FFI()
+ ffi.cdef("union foo_s { int a, b; };")
+ assert ffi.sizeof("union foo_s") == 4
+
+def test_cdef_struct_union():
+ ffi = FFI()
+ ffi.cdef("union bar_s { int a; }; struct foo_s { int b; };")
+ assert ffi.sizeof("union bar_s") == 4
+ assert ffi.sizeof("struct foo_s") == 4
+
+def test_cdef_struct_typename_1():
+ ffi = FFI()
+ ffi.cdef("typedef struct { int a; } t1; typedef struct { t1* m; } t2;")
+ assert ffi.sizeof("t2") == ffi.sizeof("void *")
+ assert ffi.sizeof("t1") == 4
+
+def test_cdef_struct_typename_2():
+ ffi = FFI()
+ ffi.cdef("typedef struct { int a; } *p1; typedef struct { p1 m; } *p2;")
+ p2 = ffi.new("p2")
+ assert ffi.sizeof(p2[0]) == ffi.sizeof("void *")
+ assert ffi.sizeof(p2[0].m) == ffi.sizeof("void *")
+
+def test_cdef_struct_anon_1():
+ ffi = FFI()
+ ffi.cdef("typedef struct { int a; } t1; struct foo_s { t1* m; };")
+ assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *")
+
+def test_cdef_struct_anon_2():
+ ffi = FFI()
+ ffi.cdef("typedef struct { int a; } *p1; struct foo_s { p1 m; };")
+ assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *")
+
+def test_cdef_struct_anon_3():
+ ffi = FFI()
+ ffi.cdef("typedef struct { int a; } **pp; struct foo_s { pp m; };")
+ assert ffi.sizeof("struct foo_s") == ffi.sizeof("void *")
+
+def test_math_sin():
+ ffi = FFI()
+ ffi.cdef("double sin(double);")
+ m = ffi.dlopen('m')
+ x = m.sin(1.23)
+ assert x == math.sin(1.23)
diff --git a/lib_pypy/_cffi1/test_ffi_obj.py b/lib_pypy/_cffi1/test_ffi_obj.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_cffi1/test_ffi_obj.py
@@ -0,0 +1,159 @@
+import py
+import _cffi_backend as _cffi1_backend
+
+
+def test_ffi_new():
+ ffi = _cffi1_backend.FFI()
+ p = ffi.new("int *")
+ p[0] = -42
+ assert p[0] == -42
+
+def test_ffi_subclass():
+ class FOO(_cffi1_backend.FFI):
+ def __init__(self, x):
+ self.x = x
+ foo = FOO(42)
+ assert foo.x == 42
+ p = foo.new("int *")
+ assert p[0] == 0
+
+def test_ffi_no_argument():
+ py.test.raises(TypeError, _cffi1_backend.FFI, 42)
+
+def test_ffi_cache_type():
+ ffi = _cffi1_backend.FFI()
+ t1 = ffi.typeof("int **")
+ t2 = ffi.typeof("int *")
+ assert t2.item is t1.item.item
+ assert t2 is t1.item
+ assert ffi.typeof("int[][10]") is ffi.typeof("int[][10]")
+ assert ffi.typeof("int(*)()") is ffi.typeof("int(*)()")
+
+def test_ffi_cache_type_globally():
+ ffi1 = _cffi1_backend.FFI()
+ ffi2 = _cffi1_backend.FFI()
+ t1 = ffi1.typeof("int *")
+ t2 = ffi2.typeof("int *")
+ assert t1 is t2
+
+def test_ffi_invalid():
+ ffi = _cffi1_backend.FFI()
+ # array of 10 times an "int[]" is invalid
+ py.test.raises(ValueError, ffi.typeof, "int[10][]")
+
+def test_ffi_docstrings():
+ # check that all methods of the FFI class have a docstring.
+ check_type = type(_cffi1_backend.FFI.new)
+ for methname in dir(_cffi1_backend.FFI):
+ if not methname.startswith('_'):
+ method = getattr(_cffi1_backend.FFI, methname)
+ if isinstance(method, check_type):
+ assert method.__doc__, "method FFI.%s() has no docstring" % (
+ methname,)
+
+def test_ffi_NULL():
+ NULL = _cffi1_backend.FFI.NULL
+ assert _cffi1_backend.FFI().typeof(NULL).cname == "void *"
+
+def test_ffi_no_attr():
+ ffi = _cffi1_backend.FFI()
+ py.test.raises(AttributeError, "ffi.no_such_name")
+ py.test.raises(AttributeError, "ffi.no_such_name = 42")
+ py.test.raises(AttributeError, "del ffi.no_such_name")
+
+def test_ffi_string():
+ ffi = _cffi1_backend.FFI()
+ p = ffi.new("char[]", init=b"foobar\x00baz")
+ assert ffi.string(p) == b"foobar"
+
+def test_ffi_errno():
+ # xxx not really checking errno, just checking that we can read/write it
+ ffi = _cffi1_backend.FFI()
+ ffi.errno = 42
+ assert ffi.errno == 42
+
+def test_ffi_alignof():
+ ffi = _cffi1_backend.FFI()
+ assert ffi.alignof("int") == 4
+ assert ffi.alignof("int[]") == 4
+ assert ffi.alignof("int[41]") == 4
+ assert ffi.alignof("short[41]") == 2
+ assert ffi.alignof(ffi.new("int[41]")) == 4
+ assert ffi.alignof(ffi.new("int[]", 41)) == 4
+
+def test_ffi_sizeof():
+ ffi = _cffi1_backend.FFI()
+ assert ffi.sizeof("int") == 4
+ py.test.raises(ffi.error, ffi.sizeof, "int[]")
+ assert ffi.sizeof("int[41]") == 41 * 4
+ assert ffi.sizeof(ffi.new("int[41]")) == 41 * 4
+ assert ffi.sizeof(ffi.new("int[]", 41)) == 41 * 4
+
+def test_ffi_callback():
+ ffi = _cffi1_backend.FFI()
+ assert ffi.callback("int(int)", lambda x: x + 42)(10) == 52
+ assert ffi.callback("int(*)(int)", lambda x: x + 42)(10) == 52
+ assert ffi.callback("int(int)", lambda x: x + "", -66)(10) == -66
+ assert ffi.callback("int(int)", lambda x: x + "", error=-66)(10) == -66
+
+def test_ffi_callback_decorator():
+ ffi = _cffi1_backend.FFI()
+ assert ffi.callback(ffi.typeof("int(*)(int)"))(lambda x: x + 42)(10) == 52
+ deco = ffi.callback("int(int)", error=-66)
+ assert deco(lambda x: x + "")(10) == -66
+ assert deco(lambda x: x + 42)(10) == 52
+
+def test_ffi_getctype():
+ ffi = _cffi1_backend.FFI()
+ assert ffi.getctype("int") == "int"
+ assert ffi.getctype("int", 'x') == "int x"
+ assert ffi.getctype("int*") == "int *"
+ assert ffi.getctype("int*", '') == "int *"
+ assert ffi.getctype("int*", 'x') == "int * x"
+ assert ffi.getctype("int", '*') == "int *"
+ assert ffi.getctype("int", replace_with=' * x ') == "int * x"
+ assert ffi.getctype(ffi.typeof("int*"), '*') == "int * *"
+ assert ffi.getctype("int", '[5]') == "int[5]"
+ assert ffi.getctype("int[5]", '[6]') == "int[6][5]"
+ assert ffi.getctype("int[5]", '(*)') == "int(*)[5]"
+ # special-case for convenience: automatically put '()' around '*'
+ assert ffi.getctype("int[5]", '*') == "int(*)[5]"
+ assert ffi.getctype("int[5]", '*foo') == "int(*foo)[5]"
+ assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]"
+
+def test_addressof():
+ ffi = _cffi1_backend.FFI()
+ a = ffi.new("int[10]")
+ b = ffi.addressof(a, 5)
+ b[2] = -123
+ assert a[7] == -123
+
+def test_handle():
+ ffi = _cffi1_backend.FFI()
+ x = [2, 4, 6]
+ xp = ffi.new_handle(x)
+ assert ffi.typeof(xp) == ffi.typeof("void *")
+ assert ffi.from_handle(xp) is x
+ yp = ffi.new_handle([6, 4, 2])
+ assert ffi.from_handle(yp) == [6, 4, 2]
+
+def test_ffi_cast():
+ ffi = _cffi1_backend.FFI()
+ assert ffi.cast("int(*)(int)", 0) == ffi.NULL
+ ffi.callback("int(int)") # side-effect of registering this string
+ py.test.raises(ffi.error, ffi.cast, "int(int)", 0)
+
+def test_ffi_invalid_type():
+ ffi = _cffi1_backend.FFI()
+ e = py.test.raises(ffi.error, ffi.cast, "", 0)
+ assert str(e.value) == ("identifier expected\n"
+ "\n"
+ "^")
+ e = py.test.raises(ffi.error, ffi.cast, "struct struct", 0)
+ assert str(e.value) == ("struct or union name expected\n"
+ "struct struct\n"
+ " ^")
+ e = py.test.raises(ffi.error, ffi.cast, "struct never_heard_of_s", 0)
+ assert str(e.value) == ("undefined struct/union name\n"
+ "struct never_heard_of_s\n"
+ " ^")
diff --git a/lib_pypy/_cffi1/test_new_ffi_1.py b/lib_pypy/_cffi1/test_new_ffi_1.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_cffi1/test_new_ffi_1.py
@@ -0,0 +1,1658 @@
+import py
+import platform, imp
+import sys, os, ctypes
+import cffi
+from .udir import udir
+from .recompiler import recompile
+from .support import *
+
+SIZE_OF_INT = ctypes.sizeof(ctypes.c_int)
+SIZE_OF_LONG = ctypes.sizeof(ctypes.c_long)
+SIZE_OF_SHORT = ctypes.sizeof(ctypes.c_short)
+SIZE_OF_PTR = ctypes.sizeof(ctypes.c_void_p)
+SIZE_OF_WCHAR = ctypes.sizeof(ctypes.c_wchar)
+
+
+def setup_module():
+ global ffi, construction_params
+ ffi1 = cffi.FFI()
+ DEFS = r"""
+ struct repr { short a, b, c; };
+ struct simple { int a; short b, c; };
+ struct array { int a[2]; char b[3]; };
+ struct recursive { int value; struct recursive *next; };
+ union simple_u { int a; short b, c; };
+ union init_u { char a; int b; };
+ struct four_s { int a; short b, c, d; };
+ union four_u { int a; short b, c, d; };
+ struct string { const char *name; };
+ struct ustring { const wchar_t *name; };
+ struct voidp { void *p; int *q; short *r; };
+ struct ab { int a, b; };
+ struct abc { int a, b, c; };
+
+ enum foq { A0, B0, CC0, D0 };
+ enum bar { A1, B1=-2, CC1, D1, E1 };
+ enum baz { A2=0x1000, B2=0x2000 };
+ enum foo2 { A3, B3, C3, D3 };
+ struct bar_with_e { enum foo2 e; };
+ enum noncont { A4, B4=42, C4 };
+ enum etypes {A5='!', B5='\'', C5=0x10, D5=010, E5=- 0x10, F5=-010};
+ typedef enum { Value0 = 0 } e_t, *pe_t;
+ enum e_noninj { AA3=0, BB3=0, CC3=0, DD3=0 };
+ enum e_prev { AA4, BB4=2, CC4=4, DD4=BB4, EE4, FF4=CC4, GG4=FF4 };
+
+ struct nesting { struct abc d, e; };
+ struct array2 { int a, b; int c[99]; };
+ struct align { char a; short b; char c; };
+ struct bitfield { int a:10, b:20, c:3; };
+ typedef enum { AA2, BB2, CC2 } foo_e_t;
+ typedef struct { foo_e_t f:2; } bfenum_t;
+ typedef struct { int a; } anon_foo_t;
+ typedef struct { char b, c; } anon_bar_t;
+ typedef struct named_foo_s { int a; } named_foo_t, *named_foo_p;
+ typedef struct { int a; } unnamed_foo_t, *unnamed_foo_p;
+ struct nonpacked { char a; int b; };
+ struct array0 { int len; short data[0]; };
+ struct array_no_length { int x; int a[]; };
+
+ struct nested_anon {
+ struct { int a, b; };
+ union { int c, d; };
+ };
+ struct nested_field_ofs_s {
+ struct { int a; char b; };
+ union { char c; };
+ };
+ union nested_anon_u {
+ struct { int a, b; };
+ union { int c, d; };
+ };
+ struct abc50 { int a, b; int c[50]; };
+ struct ints_and_bitfield { int a,b,c,d,e; int x:1; };
+ """
+ DEFS_PACKED = """
+ struct is_packed { char a; int b; } /*here*/;
+ """
+ if sys.platform == "win32":
+ DEFS = DEFS.replace('data[0]', 'data[1]') # not supported
+ CCODE = (DEFS + "\n#pragma pack(push,1)\n" + DEFS_PACKED +
+ "\n#pragma pack(pop)\n")
+ else:
+ CCODE = (DEFS +
+ DEFS_PACKED.replace('/*here*/', '__attribute__((packed))'))
+
+ ffi1.cdef(DEFS)
+ ffi1.cdef(DEFS_PACKED, packed=True)
+
+ outputfilename = recompile(ffi1, "test_new_ffi_1", CCODE,
+ tmpdir=str(udir))
+ module = imp.load_dynamic("test_new_ffi_1", outputfilename)
+ ffi = module.ffi
+ construction_params = (ffi1, CCODE)
+
+
+class TestNewFFI1:
+
+ def test_integer_ranges(self):
+ for (c_type, size) in [('char', 1),
+ ('short', 2),
+ ('short int', 2),
+ ('', 4),
+ ('int', 4),
+ ('long', SIZE_OF_LONG),
+ ('long int', SIZE_OF_LONG),
+ ('long long', 8),
+ ('long long int', 8),
+ ]:
+ for unsigned in [None, False, True]:
+ c_decl = {None: '',
+ False: 'signed ',
+ True: 'unsigned '}[unsigned] + c_type
+ if c_decl == 'char' or c_decl == '':
+ continue
+ self._test_int_type(ffi, c_decl, size, unsigned)
+
+ def test_fixedsize_int(self):
+ for size in [1, 2, 4, 8]:
+ self._test_int_type(ffi, 'int%d_t' % (8*size), size, False)
+ self._test_int_type(ffi, 'uint%d_t' % (8*size), size, True)
+ self._test_int_type(ffi, 'intptr_t', SIZE_OF_PTR, False)
+ self._test_int_type(ffi, 'uintptr_t', SIZE_OF_PTR, True)
+ self._test_int_type(ffi, 'ptrdiff_t', SIZE_OF_PTR, False)
+ self._test_int_type(ffi, 'size_t', SIZE_OF_PTR, True)
+ self._test_int_type(ffi, 'ssize_t', SIZE_OF_PTR, False)
+
+ def _test_int_type(self, ffi, c_decl, size, unsigned):
+ if unsigned:
+ min = 0
+ max = (1 << (8*size)) - 1
+ else:
+ min = -(1 << (8*size-1))
+ max = (1 << (8*size-1)) - 1
+ min = int(min)
+ max = int(max)
+ p = ffi.cast(c_decl, min)
+ assert p != min # no __eq__(int)
+ assert bool(p) is True
+ assert int(p) == min
+ p = ffi.cast(c_decl, max)
+ assert int(p) == max
+ p = ffi.cast(c_decl, long(max))
+ assert int(p) == max
+ q = ffi.cast(c_decl, min - 1)
+ assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
+ q = ffi.cast(c_decl, long(min - 1))
+ assert ffi.typeof(q) is ffi.typeof(p) and int(q) == max
+ assert q != p
+ assert int(q) == int(p)
+ assert hash(q) != hash(p) # unlikely
+ c_decl_ptr = '%s *' % c_decl
+ py.test.raises(OverflowError, ffi.new, c_decl_ptr, min - 1)
+ py.test.raises(OverflowError, ffi.new, c_decl_ptr, max + 1)
+ py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(min - 1))
+ py.test.raises(OverflowError, ffi.new, c_decl_ptr, long(max + 1))
+ assert ffi.new(c_decl_ptr, min)[0] == min
+ assert ffi.new(c_decl_ptr, max)[0] == max
+ assert ffi.new(c_decl_ptr, long(min))[0] == min
+ assert ffi.new(c_decl_ptr, long(max))[0] == max
+
+ def test_new_unsupported_type(self):
+ e = py.test.raises(TypeError, ffi.new, "int")
+ assert str(e.value) == "expected a pointer or array ctype, got 'int'"
+
+ def test_new_single_integer(self):
+ p = ffi.new("int *") # similar to ffi.new("int[1]")
+ assert p[0] == 0
+ p[0] = -123
+ assert p[0] == -123
+ p = ffi.new("int *", -42)
+ assert p[0] == -42
+ assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT
+
+ def test_new_array_no_arg(self):
+ p = ffi.new("int[10]")
+ # the object was zero-initialized:
+ for i in range(10):
+ assert p[i] == 0
+
+ def test_array_indexing(self):
+ p = ffi.new("int[10]")
+ p[0] = 42
+ p[9] = 43
+ assert p[0] == 42
+ assert p[9] == 43
+ py.test.raises(IndexError, "p[10]")
+ py.test.raises(IndexError, "p[10] = 44")
+ py.test.raises(IndexError, "p[-1]")
+ py.test.raises(IndexError, "p[-1] = 44")
+
+ def test_new_array_args(self):
+ # this tries to be closer to C: where we say "int x[5] = {10, 20, ..}"
+ # then here we must enclose the items in a list
+ p = ffi.new("int[5]", [10, 20, 30, 40, 50])
+ assert p[0] == 10
+ assert p[1] == 20
+ assert p[2] == 30
+ assert p[3] == 40
+ assert p[4] == 50
+ p = ffi.new("int[4]", [25])
+ assert p[0] == 25
+ assert p[1] == 0 # follow C convention rather than LuaJIT's
+ assert p[2] == 0
+ assert p[3] == 0
+ p = ffi.new("int[4]", [ffi.cast("int", -5)])
+ assert p[0] == -5
+ assert repr(p) == "<cdata 'int[4]' owning %d bytes>" % (4*SIZE_OF_INT)
+
+ def test_new_array_varsize(self):
+ p = ffi.new("int[]", 10) # a single integer is the length
+ assert p[9] == 0
+ py.test.raises(IndexError, "p[10]")
+ #
+ py.test.raises(TypeError, ffi.new, "int[]")
+ #
+ p = ffi.new("int[]", [-6, -7]) # a list is all the items, like C
+ assert p[0] == -6
+ assert p[1] == -7
+ py.test.raises(IndexError, "p[2]")
+ assert repr(p) == "<cdata 'int[]' owning %d bytes>" % (2*SIZE_OF_INT)
+ #
+ p = ffi.new("int[]", 0)
+ py.test.raises(IndexError, "p[0]")
+ py.test.raises(ValueError, ffi.new, "int[]", -1)
+ assert repr(p) == "<cdata 'int[]' owning 0 bytes>"
+
+ def test_pointer_init(self):
+ n = ffi.new("int *", 24)
+ a = ffi.new("int *[10]", [ffi.NULL, ffi.NULL, n, n, ffi.NULL])
+ for i in range(10):
+ if i not in (2, 3):
+ assert a[i] == ffi.NULL
+ assert a[2] == a[3] == n
+
+ def test_cannot_cast(self):
+ a = ffi.new("short int[10]")
+ e = py.test.raises(TypeError, ffi.new, "long int **", a)
+ msg = str(e.value)
+ assert "'short[10]'" in msg and "'long *'" in msg
+
+ def test_new_pointer_to_array(self):
+ a = ffi.new("int[4]", [100, 102, 104, 106])
+ p = ffi.new("int **", a)
+ assert p[0] == ffi.cast("int *", a)
+ assert p[0][2] == 104
+ p = ffi.cast("int *", a)
+ assert p[0] == 100
+ assert p[1] == 102
+ assert p[2] == 104
+ assert p[3] == 106
+ # keepalive: a
+
+ def test_pointer_direct(self):
+ p = ffi.cast("int*", 0)
+ assert p is not None
+ assert bool(p) is False
+ assert p == ffi.cast("int*", 0)
+ assert p != None
+ assert repr(p) == "<cdata 'int *' NULL>"
+ a = ffi.new("int[]", [123, 456])
+ p = ffi.cast("int*", a)
+ assert bool(p) is True
+ assert p == ffi.cast("int*", a)
+ assert p != ffi.cast("int*", 0)
+ assert p[0] == 123
+ assert p[1] == 456
+
+ def test_repr(self):
+ typerepr = "<ctype '%s'>"
+ p = ffi.cast("short unsigned int", 0)
+ assert repr(p) == "<cdata 'unsigned short' 0>"
+ assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
+ p = ffi.cast("unsigned short int", 0)
+ assert repr(p) == "<cdata 'unsigned short' 0>"
+ assert repr(ffi.typeof(p)) == typerepr % "unsigned short"
+ p = ffi.cast("int*", 0)
+ assert repr(p) == "<cdata 'int *' NULL>"
+ assert repr(ffi.typeof(p)) == typerepr % "int *"
+ #
+ p = ffi.new("int*")
+ assert repr(p) == "<cdata 'int *' owning %d bytes>" % SIZE_OF_INT
+ assert repr(ffi.typeof(p)) == typerepr % "int *"
+ p = ffi.new("int**")
+ assert repr(p) == "<cdata 'int * *' owning %d bytes>" % SIZE_OF_PTR
+ assert repr(ffi.typeof(p)) == typerepr % "int * *"
+ p = ffi.new("int [2]")
+ assert repr(p) == "<cdata 'int[2]' owning %d bytes>" % (2*SIZE_OF_INT)
+ assert repr(ffi.typeof(p)) == typerepr % "int[2]"
+ p = ffi.new("int*[2][3]")
+ assert repr(p) == "<cdata 'int *[2][3]' owning %d bytes>" % (
+ 6*SIZE_OF_PTR)
+ assert repr(ffi.typeof(p)) == typerepr % "int *[2][3]"
+ p = ffi.new("struct repr *")
+ assert repr(p) == "<cdata 'struct repr *' owning %d bytes>" % (
+ 3*SIZE_OF_SHORT)
+ assert repr(ffi.typeof(p)) == typerepr % "struct repr *"
+ #
+ q = ffi.cast("short", -123)
+ assert repr(q) == "<cdata 'short' -123>"
+ assert repr(ffi.typeof(q)) == typerepr % "short"
+ p = ffi.new("int*")
+ q = ffi.cast("short*", p)
+ assert repr(q).startswith("<cdata 'short *' 0x")
+ assert repr(ffi.typeof(q)) == typerepr % "short *"
+ p = ffi.new("int [2]")
+ q = ffi.cast("int*", p)
+ assert repr(q).startswith("<cdata 'int *' 0x")
+ assert repr(ffi.typeof(q)) == typerepr % "int *"
+ p = ffi.new("struct repr*")
+ q = ffi.cast("struct repr *", p)
+ assert repr(q).startswith("<cdata 'struct repr *' 0x")
+ assert repr(ffi.typeof(q)) == typerepr % "struct repr *"
+ prevrepr = repr(q)
+ q = q[0]
+ assert repr(q) == prevrepr.replace(' *', ' &')
+ assert repr(ffi.typeof(q)) == typerepr % "struct repr"
+
+ def test_new_array_of_array(self):
+ p = ffi.new("int[3][4]")
+ p[0][0] = 10
+ p[2][3] = 33
+ assert p[0][0] == 10
+ assert p[2][3] == 33
+ py.test.raises(IndexError, "p[1][-1]")
+
+ def test_constructor_array_of_array(self):
+ p = ffi.new("int[3][2]", [[10, 11], [12, 13], [14, 15]])
+ assert p[2][1] == 15
+
+ def test_new_array_of_pointer_1(self):
+ n = ffi.new("int*", 99)
+ p = ffi.new("int*[4]")
+ p[3] = n
+ a = p[3]
+ assert repr(a).startswith("<cdata 'int *' 0x")
+ assert a[0] == 99
+
+ def test_new_array_of_pointer_2(self):
+ n = ffi.new("int[1]", [99])
+ p = ffi.new("int*[4]")
+ p[3] = n
+ a = p[3]
+ assert repr(a).startswith("<cdata 'int *' 0x")
+ assert a[0] == 99
+
+ def test_char(self):
+ assert ffi.new("char*", b"\xff")[0] == b'\xff'
+ assert ffi.new("char*")[0] == b'\x00'
+ assert int(ffi.cast("char", 300)) == 300 - 256
+ assert bool(ffi.cast("char", 0))
+ py.test.raises(TypeError, ffi.new, "char*", 32)
+ py.test.raises(TypeError, ffi.new, "char*", u+"x")
+ py.test.raises(TypeError, ffi.new, "char*", b"foo")
+ #
+ p = ffi.new("char[]", [b'a', b'b', b'\x9c'])
+ assert len(p) == 3
+ assert p[0] == b'a'
+ assert p[1] == b'b'
+ assert p[2] == b'\x9c'
+ p[0] = b'\xff'
+ assert p[0] == b'\xff'
+ p = ffi.new("char[]", b"abcd")
+ assert len(p) == 5
+ assert p[4] == b'\x00' # like in C, with: char[] p = "abcd";
+ #
+ p = ffi.new("char[4]", b"ab")
+ assert len(p) == 4
+ assert [p[i] for i in range(4)] == [b'a', b'b', b'\x00', b'\x00']
+ p = ffi.new("char[2]", b"ab")
+ assert len(p) == 2
+ assert [p[i] for i in range(2)] == [b'a', b'b']
+ py.test.raises(IndexError, ffi.new, "char[2]", b"abc")
+
+ def check_wchar_t(self, ffi):
+ try:
+ ffi.cast("wchar_t", 0)
+ except NotImplementedError:
+ py.test.skip("NotImplementedError: wchar_t")
+
+ def test_wchar_t(self):
+ self.check_wchar_t(ffi)
+ assert ffi.new("wchar_t*", u+'x')[0] == u+'x'
+ assert ffi.new("wchar_t*", u+'\u1234')[0] == u+'\u1234'
+ if SIZE_OF_WCHAR > 2:
+ assert ffi.new("wchar_t*", u+'\U00012345')[0] == u+'\U00012345'
+ else:
+ py.test.raises(TypeError, ffi.new, "wchar_t*", u+'\U00012345')
+ assert ffi.new("wchar_t*")[0] == u+'\x00'
+ assert int(ffi.cast("wchar_t", 300)) == 300
+ assert bool(ffi.cast("wchar_t", 0))
+ py.test.raises(TypeError, ffi.new, "wchar_t*", 32)
+ py.test.raises(TypeError, ffi.new, "wchar_t*", "foo")
+ #
+ p = ffi.new("wchar_t[]", [u+'a', u+'b', u+'\u1234'])
+ assert len(p) == 3
+ assert p[0] == u+'a'
+ assert p[1] == u+'b' and type(p[1]) is unicode
+ assert p[2] == u+'\u1234'
+ p[0] = u+'x'
+ assert p[0] == u+'x' and type(p[0]) is unicode
+ p[1] = u+'\u1357'
+ assert p[1] == u+'\u1357'
+ p = ffi.new("wchar_t[]", u+"abcd")
+ assert len(p) == 5
+ assert p[4] == u+'\x00'
+ p = ffi.new("wchar_t[]", u+"a\u1234b")
+ assert len(p) == 4
+ assert p[1] == u+'\u1234'
+ #
+ p = ffi.new("wchar_t[]", u+'\U00023456')
+ if SIZE_OF_WCHAR == 2:
+ assert sys.maxunicode == 0xffff
+ assert len(p) == 3
+ assert p[0] == u+'\ud84d'
+ assert p[1] == u+'\udc56'
+ assert p[2] == u+'\x00'
+ else:
+ assert len(p) == 2
+ assert p[0] == u+'\U00023456'
+ assert p[1] == u+'\x00'
+ #
+ p = ffi.new("wchar_t[4]", u+"ab")
+ assert len(p) == 4
+ assert [p[i] for i in range(4)] == [u+'a', u+'b', u+'\x00', u+'\x00']
+ p = ffi.new("wchar_t[2]", u+"ab")
+ assert len(p) == 2
+ assert [p[i] for i in range(2)] == [u+'a', u+'b']
+ py.test.raises(IndexError, ffi.new, "wchar_t[2]", u+"abc")
+
+ def test_none_as_null_doesnt_work(self):
+ p = ffi.new("int*[1]")
+ assert p[0] is not None
+ assert p[0] != None
+ assert p[0] == ffi.NULL
+ assert repr(p[0]) == "<cdata 'int *' NULL>"
+ #
+ n = ffi.new("int*", 99)
+ p = ffi.new("int*[]", [n])
+ assert p[0][0] == 99
+ py.test.raises(TypeError, "p[0] = None")
+ p[0] = ffi.NULL
+ assert p[0] == ffi.NULL
+
+ def test_float(self):
+ p = ffi.new("float[]", [-2, -2.5])
+ assert p[0] == -2.0
+ assert p[1] == -2.5
+ p[1] += 17.75
+ assert p[1] == 15.25
+ #
+ p = ffi.new("float*", 15.75)
+ assert p[0] == 15.75
+ py.test.raises(TypeError, int, p)
+ py.test.raises(TypeError, float, p)
+ p[0] = 0.0
+ assert bool(p) is True
+ #
+ p = ffi.new("float*", 1.1)
+ f = p[0]
+ assert f != 1.1 # because of rounding effect
+ assert abs(f - 1.1) < 1E-7
+ #
+ INF = 1E200 * 1E200
+ assert 1E200 != INF
+ p[0] = 1E200
+ assert p[0] == INF # infinite, not enough precision
+
+ def test_struct_simple(self):
+ s = ffi.new("struct simple*")
+ assert s.a == s.b == s.c == 0
+ s.b = -23
+ assert s.b == -23
+ py.test.raises(OverflowError, "s.b = 32768")
+ #
+ s = ffi.new("struct simple*", [-2, -3])
+ assert s.a == -2
+ assert s.b == -3
+ assert s.c == 0
+ py.test.raises((AttributeError, TypeError), "del s.a")
+ assert repr(s) == "<cdata 'struct simple *' owning %d bytes>" % (
+ SIZE_OF_INT + 2 * SIZE_OF_SHORT)
+ #
+ py.test.raises(ValueError, ffi.new, "struct simple*", [1, 2, 3, 4])
+
+ def test_constructor_struct_from_dict(self):
+ s = ffi.new("struct simple*", {'b': 123, 'c': 456})
+ assert s.a == 0
+ assert s.b == 123
+ assert s.c == 456
+ py.test.raises(KeyError, ffi.new, "struct simple*", {'d': 456})
+
+ def test_struct_pointer(self):
+ s = ffi.new("struct simple*")
+ assert s[0].a == s[0].b == s[0].c == 0
+ s[0].b = -23
+ assert s[0].b == s.b == -23
+ py.test.raises(OverflowError, "s[0].b = -32769")
+ py.test.raises(IndexError, "s[1]")
+
+ def test_struct_opaque(self):
+ py.test.raises(ffi.error, ffi.new, "struct baz*")
+ # should 'ffi.new("struct baz **") work? it used to, but it was
+ # not particularly useful...
+ py.test.raises(ffi.error, ffi.new, "struct baz**")
+
+ def test_pointer_to_struct(self):
+ s = ffi.new("struct simple *")
+ s.a = -42
+ assert s[0].a == -42
+ p = ffi.new("struct simple **", s)
+ assert p[0].a == -42
+ assert p[0][0].a == -42
+ p[0].a = -43
+ assert s.a == -43
+ assert s[0].a == -43
+ p[0][0].a = -44
+ assert s.a == -44
+ assert s[0].a == -44
+ s.a = -45
+ assert p[0].a == -45
+ assert p[0][0].a == -45
+ s[0].a = -46
+ assert p[0].a == -46
+ assert p[0][0].a == -46
+
+ def test_constructor_struct_of_array(self):
+ s = ffi.new("struct array *", [[10, 11], [b'a', b'b', b'c']])
+ assert s.a[1] == 11
+ assert s.b[2] == b'c'
+ s.b[1] = b'X'
+ assert s.b[0] == b'a'
+ assert s.b[1] == b'X'
+ assert s.b[2] == b'c'
+
+ def test_recursive_struct(self):
+ s = ffi.new("struct recursive*")
+ t = ffi.new("struct recursive*")
+ s.value = 123
+ s.next = t
+ t.value = 456
+ assert s.value == 123
+ assert s.next.value == 456
+
+ def test_union_simple(self):
+ u = ffi.new("union simple_u*")
+ assert u.a == u.b == u.c == 0
+ u.b = -23
+ assert u.b == -23
+ assert u.a != 0
+ py.test.raises(OverflowError, "u.b = 32768")
+ #
More information about the pypy-commit
mailing list