12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076 |
- #
- # DEPRECATED: implementation for ffi.verify()
- #
- import sys, imp
- from . import model
- from .error import VerificationError
-
-
- class VCPythonEngine(object):
- _class_key = 'x'
- _gen_python_module = True
-
- def __init__(self, verifier):
- self.verifier = verifier
- self.ffi = verifier.ffi
- self._struct_pending_verification = {}
- self._types_of_builtin_functions = {}
-
- def patch_extension_kwds(self, kwds):
- pass
-
- def find_module(self, module_name, path, so_suffixes):
- try:
- f, filename, descr = imp.find_module(module_name, path)
- except ImportError:
- return None
- if f is not None:
- f.close()
- # Note that after a setuptools installation, there are both .py
- # and .so files with the same basename. The code here relies on
- # imp.find_module() locating the .so in priority.
- if descr[0] not in so_suffixes:
- return None
- return filename
-
- def collect_types(self):
- self._typesdict = {}
- self._generate("collecttype")
-
- 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 _do_collect_type(self, tp):
- if ((not isinstance(tp, model.PrimitiveType)
- or tp.name == 'long double')
- and tp not in self._typesdict):
- num = len(self._typesdict)
- self._typesdict[tp] = num
-
- def write_source_to_f(self):
- self.collect_types()
- #
- # The new module will have a _cffi_setup() function that receives
- # objects from the ffi world, and that calls some setup code in
- # the module. This setup code is split in several independent
- # functions, e.g. one per constant. The functions are "chained"
- # by ending in a tail call to each other.
- #
- # This is further split in two chained lists, depending on if we
- # can do it at import-time or if we must wait for _cffi_setup() to
- # provide us with the <ctype> objects. This is needed because we
- # need the values of the enum constants in order to build the
- # <ctype 'enum'> that we may have to pass to _cffi_setup().
- #
- # 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 = ['((void)lib,0)', '((void)lib,0)']
- #
- prnt = self._prnt
- # first paste some standard set of lines that are mostly '#define'
- prnt(cffimod_header)
- prnt()
- # then paste the C source given by the user, verbatim.
- prnt(self.verifier.preamble)
- prnt()
- #
- # call generate_cpy_xxx_decl(), for every xxx found from
- # ffi._parser._declarations. This generates all the functions.
- self._generate("decl")
- #
- # implement the function _cffi_setup_custom() as calling the
- # head of the chained list.
- self._generate_setup_custom()
- prnt()
- #
- # produce the method table, including the entries for the
- # generated Python->C function wrappers, which are done
- # by generate_cpy_function_method().
- prnt('static PyMethodDef _cffi_methods[] = {')
- self._generate("method")
- prnt(' {"_cffi_setup", _cffi_setup, METH_VARARGS, NULL},')
- prnt(' {NULL, NULL, 0, NULL} /* Sentinel */')
- prnt('};')
- prnt()
- #
- # standard init.
- modname = self.verifier.get_module_name()
- constants = self._chained_list_constants[False]
- prnt('#if PY_MAJOR_VERSION >= 3')
- prnt()
- prnt('static struct PyModuleDef _cffi_module_def = {')
- prnt(' PyModuleDef_HEAD_INIT,')
- prnt(' "%s",' % modname)
- prnt(' NULL,')
- prnt(' -1,')
- prnt(' _cffi_methods,')
- prnt(' NULL, NULL, NULL, NULL')
- prnt('};')
- prnt()
- prnt('PyMODINIT_FUNC')
- prnt('PyInit_%s(void)' % modname)
- prnt('{')
- prnt(' PyObject *lib;')
- prnt(' lib = PyModule_Create(&_cffi_module_def);')
- prnt(' if (lib == NULL)')
- prnt(' return NULL;')
- prnt(' if (%s < 0 || _cffi_init() < 0) {' % (constants,))
- prnt(' Py_DECREF(lib);')
- prnt(' return NULL;')
- prnt(' }')
- prnt(' return lib;')
- prnt('}')
- prnt()
- prnt('#else')
- prnt()
- prnt('PyMODINIT_FUNC')
- prnt('init%s(void)' % modname)
- prnt('{')
- prnt(' PyObject *lib;')
- prnt(' lib = Py_InitModule("%s", _cffi_methods);' % modname)
- prnt(' if (lib == NULL)')
- prnt(' return;')
- prnt(' if (%s < 0 || _cffi_init() < 0)' % (constants,))
- prnt(' return;')
- prnt(' return;')
- prnt('}')
- prnt()
- prnt('#endif')
-
- def load_library(self, flags=None):
- # XXX review all usages of 'self' here!
- # import it as a new extension module
- imp.acquire_lock()
- try:
- 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 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
- self._load(module, 'loading')
- #
- # the C code will need the <ctype> objects. Collect them in
- # order in a list.
- revmapping = dict([(value, key)
- for (key, value) in self._typesdict.items()])
- lst = [revmapping[i] for i in range(len(revmapping))]
- lst = list(map(self.ffi._get_cached_btype, lst))
- #
- # build the FFILibrary class and instance and call _cffi_setup().
- # this will set up some fields like '_cffi_types', and only then
- # it will invoke the chained list of functions that will really
- # build (notably) the constant objects, as <cdata> if they are
- # pointers, and store them as attributes on the 'library' object.
- class FFILibrary(object):
- _cffi_python_module = module
- _cffi_ffi = self.ffi
- _cffi_dir = []
- def __dir__(self):
- return FFILibrary._cffi_dir + list(self.__dict__)
- library = FFILibrary()
- if module._cffi_setup(lst, VerificationError, library):
- import warnings
- warnings.warn("reimporting %r might overwrite older definitions"
- % (self.verifier.get_module_name()))
- #
- # finally, call the loaded_cpy_xxx() functions. This will perform
- # the final adjustments, like copying the Python->C wrapper
- # functions from the module to the 'library' object, and setting
- # up the FFILibrary class with properties for the global C variables.
- self._load(module, 'loaded', library=library)
- module._cffi_original_ffi = self.ffi
- module._cffi_types_of_builtin_funcs = self._types_of_builtin_functions
- return library
-
- def _get_declarations(self):
- 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():
- kind, realname = name.split(' ', 1)
- try:
- method = getattr(self, '_generate_cpy_%s_%s' % (kind,
- step_name))
- except AttributeError:
- raise VerificationError(
- "not implemented in verify(): %r" % name)
- try:
- method(tp, realname)
- except Exception as e:
- model.attach_exception_info(e, name)
- raise
-
- def _load(self, module, step_name, **kwds):
- for name, tp in self._get_declarations():
- kind, realname = name.split(' ', 1)
- method = getattr(self, '_%s_cpy_%s' % (step_name, kind))
- try:
- method(tp, realname, module, **kwds)
- except Exception as e:
- model.attach_exception_info(e, name)
- raise
-
- def _generate_nothing(self, tp, name):
- pass
-
- def _loaded_noop(self, tp, name, module, **kwds):
- pass
-
- # ----------
-
- 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, freelines):
- if isinstance(tp, model.PointerType):
- localvars.add('Py_ssize_t datasize')
- localvars.add('struct _cffi_freeme_s *large_args_free = NULL')
- freelines.add('if (large_args_free != NULL)'
- ' _cffi_free_array_arguments(large_args_free);')
-
- 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(' %s = ((size_t)datasize) <= 640 ? '
- 'alloca((size_t)datasize) : NULL;' % (tovar,))
- self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, '
- '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar))
- self._prnt(' datasize, &large_args_free) < 0)')
- 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() and tp.name != '_Bool':
- 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.StructOrUnion):
- 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: generates no code so far
-
- _generate_cpy_typedef_collecttype = _generate_nothing
- _generate_cpy_typedef_decl = _generate_nothing
- _generate_cpy_typedef_method = _generate_nothing
- _loading_cpy_typedef = _loaded_noop
- _loaded_cpy_typedef = _loaded_noop
-
- # ----------
- # function declarations
-
- def _generate_cpy_function_collecttype(self, tp, name):
- assert isinstance(tp, model.FunctionPtrType)
- if tp.ellipsis:
- self._do_collect_type(tp)
- else:
- # don't call _do_collect_type(tp) in this common case,
- # otherwise test_autofilled_struct_as_argument fails
- for type in tp.args:
- self._do_collect_type(type)
- self._do_collect_type(tp.result)
-
- 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_const(False, name, tp)
- return
- prnt = self._prnt
- numargs = len(tp.args)
- if numargs == 0:
- argname = 'noarg'
- elif numargs == 1:
- argname = 'arg0'
- else:
- argname = 'args'
- prnt('static PyObject *')
- prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname))
- prnt('{')
- #
- context = 'argument of %s' % name
- for i, type in enumerate(tp.args):
- prnt(' %s;' % type.get_c_name(' x%d' % i, context))
- #
- localvars = set()
- freelines = set()
- for type in tp.args:
- self._extra_local_variables(type, localvars, freelines)
- for decl in sorted(localvars):
- prnt(' %s;' % (decl,))
- #
- if not isinstance(tp.result, model.VoidType):
- result_code = 'result = '
- context = 'result of %s' % name
- prnt(' %s;' % tp.result.get_c_name(' result', context))
- prnt(' PyObject *pyresult;')
- else:
- 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();')
- prnt(' { %s%s(%s); }' % (
- result_code, name,
- ', '.join(['x%d' % i for i in range(len(tp.args))])))
- 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(' pyresult = %s;' %
- self._convert_expr_from_c(tp.result, 'result', 'result type'))
- for freeline in freelines:
- prnt(' ' + freeline)
- prnt(' return pyresult;')
- else:
- for freeline in freelines:
- prnt(' ' + freeline)
- prnt(' Py_INCREF(Py_None);')
- prnt(' return Py_None;')
- prnt('}')
- prnt()
-
- def _generate_cpy_function_method(self, tp, name):
- if tp.ellipsis:
- return
- numargs = len(tp.args)
- if numargs == 0:
- meth = 'METH_NOARGS'
- elif numargs == 1:
- meth = 'METH_O'
- else:
- meth = 'METH_VARARGS'
- self._prnt(' {"%s", _cffi_f_%s, %s, NULL},' % (name, name, meth))
-
- _loading_cpy_function = _loaded_noop
-
- def _loaded_cpy_function(self, tp, name, module, library):
- if tp.ellipsis:
- return
- func = getattr(module, name)
- setattr(library, name, func)
- self._types_of_builtin_functions[func] = tp
-
- # ----------
- # named structs
-
- _generate_cpy_struct_collecttype = _generate_nothing
- def _generate_cpy_struct_decl(self, tp, name):
- assert name == tp.name
- self._generate_struct_or_union_decl(tp, 'struct', name)
- def _generate_cpy_struct_method(self, tp, name):
- self._generate_struct_or_union_method(tp, 'struct', name)
- def _loading_cpy_struct(self, tp, name, module):
- self._loading_struct_or_union(tp, 'struct', name, module)
- def _loaded_cpy_struct(self, tp, name, module, **kwds):
- self._loaded_struct_or_union(tp)
-
- _generate_cpy_union_collecttype = _generate_nothing
- def _generate_cpy_union_decl(self, tp, name):
- assert name == tp.name
- self._generate_struct_or_union_decl(tp, 'union', name)
- def _generate_cpy_union_method(self, tp, name):
- self._generate_struct_or_union_method(tp, 'union', name)
- def _loading_cpy_union(self, tp, name, module):
- self._loading_struct_or_union(tp, 'union', name, module)
- def _loaded_cpy_union(self, tp, name, module, **kwds):
- self._loaded_struct_or_union(tp)
-
- def _generate_struct_or_union_decl(self, tp, prefix, name):
- if tp.fldnames is None:
- return # nothing to do with opaque structs
- checkfuncname = '_cffi_check_%s_%s' % (prefix, name)
- layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name)
- cname = ('%s %s' % (prefix, name)).strip()
- #
- prnt = self._prnt
- 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, 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
- 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, quals=fqual),
- fname))
- except VerificationError as e:
- prnt(' /* %s */' % str(e)) # cannot verify it, ignore
- prnt('}')
- prnt('static PyObject *')
- prnt('%s(PyObject *self, PyObject *noarg)' % (layoutfuncname,))
- prnt('{')
- prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname)
- prnt(' static Py_ssize_t nums[] = {')
- prnt(' sizeof(%s),' % cname)
- prnt(' offsetof(struct _cffi_aligncheck, y),')
- for fname, ftype, fbitsize, fqual in tp.enumfields():
- if fbitsize >= 0:
- continue # xxx ignore fbitsize for now
- prnt(' offsetof(%s, %s),' % (cname, fname))
- if isinstance(ftype, model.ArrayType) and ftype.length is None:
- prnt(' 0, /* %s */' % ftype._get_c_name())
- else:
- 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,))
- prnt('}')
- prnt()
-
- def _generate_struct_or_union_method(self, tp, prefix, name):
- if tp.fldnames is None:
- return # nothing to do with opaque structs
- layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name)
- self._prnt(' {"%s", %s, METH_NOARGS, NULL},' % (layoutfuncname,
- layoutfuncname))
-
- def _loading_struct_or_union(self, tp, prefix, name, module):
- if tp.fldnames is None:
- return # nothing to do with opaque structs
- layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name)
- #
- function = getattr(module, layoutfuncname)
- layout = function()
- if isinstance(tp, model.StructOrUnion) and tp.partial:
- # use the function()'s sizes and offsets to guide the
- # layout of the struct
- totalsize = layout[0]
- totalalignment = layout[1]
- fieldofs = layout[2::2]
- fieldsize = layout[3::2]
- tp.force_flatten()
- assert len(fieldofs) == len(fieldsize) == len(tp.fldnames)
- tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment
- else:
- cname = ('%s %s' % (prefix, name)).strip()
- self._struct_pending_verification[tp] = layout, cname
-
- def _loaded_struct_or_union(self, tp):
- if tp.fldnames is None:
- return # nothing to do with opaque structs
- self.ffi._get_cached_btype(tp) # force 'fixedlayout' to be considered
-
- if tp in self._struct_pending_verification:
- # check that the layout sizes and offsets match the real ones
- def check(realvalue, expectedvalue, msg):
- if realvalue != expectedvalue:
- raise VerificationError(
- "%s (we have %d, but C compiler says %d)"
- % (msg, expectedvalue, realvalue))
- ffi = self.ffi
- BStruct = ffi._get_cached_btype(tp)
- layout, cname = self._struct_pending_verification.pop(tp)
- check(layout[0], ffi.sizeof(BStruct), "wrong total size")
- check(layout[1], ffi.alignof(BStruct), "wrong total alignment")
- i = 2
- for fname, ftype, fbitsize, fqual in tp.enumfields():
- if fbitsize >= 0:
- continue # xxx ignore fbitsize for now
- check(layout[i], ffi.offsetof(BStruct, fname),
- "wrong offset for field %r" % (fname,))
- if layout[i+1] != 0:
- BField = ffi._get_cached_btype(ftype)
- check(layout[i+1], ffi.sizeof(BField),
- "wrong size for field %r" % (fname,))
- i += 2
- assert i == len(layout)
-
- # ----------
- # 'anonymous' declarations. These are produced for anonymous structs
- # or unions; the 'name' is obtained by a typedef.
-
- _generate_cpy_anonymous_collecttype = _generate_nothing
-
- def _generate_cpy_anonymous_decl(self, tp, name):
- if isinstance(tp, model.EnumType):
- self._generate_cpy_enum_decl(tp, name, '')
- else:
- self._generate_struct_or_union_decl(tp, '', name)
-
- def _generate_cpy_anonymous_method(self, tp, name):
- if not isinstance(tp, model.EnumType):
- self._generate_struct_or_union_method(tp, '', name)
-
- def _loading_cpy_anonymous(self, tp, name, module):
- if isinstance(tp, model.EnumType):
- self._loading_cpy_enum(tp, name, module)
- else:
- self._loading_struct_or_union(tp, '', name, module)
-
- def _loaded_cpy_anonymous(self, tp, name, module, **kwds):
- if isinstance(tp, model.EnumType):
- self._loaded_cpy_enum(tp, name, module, **kwds)
- else:
- self._loaded_struct_or_union(tp)
-
- # ----------
- # constants, likely declared with '#define'
-
- def _generate_cpy_const(self, is_int, name, tp=None, category='const',
- 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)
- prnt('{')
- prnt(' PyObject *o;')
- prnt(' int res;')
- if not is_int:
- prnt(' %s;' % (vartp or tp).get_c_name(' i', name))
- 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
- else:
- realexpr = name
- prnt(' i = (%s);' % (realexpr,))
- prnt(' o = %s;' % (self._convert_expr_from_c(tp, 'i',
- 'variable type'),))
- assert delayed
- else:
- prnt(' o = _cffi_from_c_int_const(%s);' % name)
- prnt(' if (o == NULL)')
- prnt(' return -1;')
- if size_too:
- prnt(' {')
- prnt(' PyObject *o1 = o;')
- prnt(' o = Py_BuildValue("On", o1, (Py_ssize_t)sizeof(%s));'
- % (name,))
- prnt(' Py_DECREF(o1);')
- prnt(' if (o == NULL)')
- prnt(' return -1;')
- prnt(' }')
- prnt(' res = PyObject_SetAttrString(lib, "%s", o);' % name)
- prnt(' Py_DECREF(o);')
- prnt(' if (res < 0)')
- prnt(' return -1;')
- prnt(' return %s;' % self._chained_list_constants[delayed])
- self._chained_list_constants[delayed] = funcname + '(lib)'
- 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)
-
- _generate_cpy_constant_method = _generate_nothing
- _loading_cpy_constant = _loaded_noop
- _loaded_cpy_constant = _loaded_noop
-
- # ----------
- # 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_')
- return '_cffi_e_%s_%s' % (prefix, name)
-
- def _generate_cpy_enum_decl(self, tp, name, prefix='enum'):
- if tp.partial:
- for enumerator in tp.enumerators:
- self._generate_cpy_const(True, enumerator, delayed=False)
- return
- #
- funcname = self._enum_funcname(prefix, name)
- prnt = self._prnt
- prnt('static int %s(PyObject *lib)' % funcname)
- prnt('{')
- for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
- 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('}')
- prnt()
-
- _generate_cpy_enum_collecttype = _generate_nothing
- _generate_cpy_enum_method = _generate_nothing
-
- def _loading_cpy_enum(self, tp, name, module):
- if tp.partial:
- enumvalues = [getattr(module, enumerator)
- for enumerator in tp.enumerators]
- tp.enumvalues = tuple(enumvalues)
- tp.partial_resolved = True
-
- def _loaded_cpy_enum(self, tp, name, module, library):
- for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
- setattr(library, enumerator, enumvalue)
-
- # ----------
- # macros: for now only for integers
-
- 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)
-
- _generate_cpy_macro_collecttype = _generate_nothing
- _generate_cpy_macro_method = _generate_nothing
- _loading_cpy_macro = _loaded_noop
- _loaded_cpy_macro = _loaded_noop
-
- # ----------
- # global variables
-
- def _generate_cpy_variable_collecttype(self, tp, name):
- if isinstance(tp, model.ArrayType):
- tp_ptr = model.PointerType(tp.item)
- else:
- tp_ptr = model.PointerType(tp)
- self._do_collect_type(tp_ptr)
-
- def _generate_cpy_variable_decl(self, tp, name):
- if isinstance(tp, model.ArrayType):
- tp_ptr = model.PointerType(tp.item)
- self._generate_cpy_const(False, name, tp, vartp=tp_ptr,
- size_too = tp.length_is_unknown())
- else:
- tp_ptr = model.PointerType(tp)
- self._generate_cpy_const(False, name, tp_ptr, category='var')
-
- _generate_cpy_variable_method = _generate_nothing
- _loading_cpy_variable = _loaded_noop
-
- def _loaded_cpy_variable(self, tp, name, module, library):
- value = getattr(library, name)
- if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the
- # sense that "a=..." is forbidden
- if tp.length_is_unknown():
- assert isinstance(value, tuple)
- (value, size) = value
- BItemType = self.ffi._get_cached_btype(tp.item)
- length, rest = divmod(size, self.ffi.sizeof(BItemType))
- if rest != 0:
- raise VerificationError(
- "bad size: %r does not seem to be an array of %s" %
- (name, tp.item))
- tp = tp.resolve_length(length)
- # 'value' is a <cdata 'type *'> which we have to replace with
- # a <cdata 'type[N]'> if the N is actually known
- if tp.length is not None:
- BArray = self.ffi._get_cached_btype(tp)
- value = self.ffi.cast(BArray, value)
- setattr(library, name, value)
- return
- # remove ptr=<cdata 'int *'> from the library instance, and replace
- # it by a property on the class, which reads/writes into ptr[0].
- ptr = value
- delattr(library, name)
- def getter(library):
- return ptr[0]
- def setter(library, value):
- ptr[0] = value
- setattr(type(library), name, property(getter, setter))
- type(library)._cffi_dir.append(name)
-
- # ----------
-
- def _generate_setup_custom(self):
- prnt = self._prnt
- prnt('static int _cffi_setup_custom(PyObject *lib)')
- prnt('{')
- prnt(' return %s;' % self._chained_list_constants[True])
- prnt('}')
-
- cffimod_header = r'''
- #include <Python.h>
- #include <stddef.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 */
- # ifndef __cplusplus
- typedef unsigned char _Bool;
- # endif
- # endif
- #else
- # include <stdint.h>
- # if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux)
- # include <alloca.h>
- # endif
- #endif
-
- #if PY_MAJOR_VERSION < 3
- # undef PyCapsule_CheckExact
- # undef PyCapsule_GetPointer
- # define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule))
- # define PyCapsule_GetPointer(capsule, name) \
- (PyCObject_AsVoidPtr(capsule))
- #endif
-
- #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_from_c__Bool PyBool_FromLong
-
- #define _cffi_to_c_double PyFloat_AsDouble
- #define _cffi_to_c_float PyFloat_AsDouble
-
- #define _cffi_from_c_int_const(x) \
- (((x) > 0) ? \
- ((unsigned long long)(x) <= (unsigned long long)LONG_MAX) ? \
- PyInt_FromLong((long)(x)) : \
- PyLong_FromUnsignedLongLong((unsigned long long)(x)) : \
- ((long long)(x) >= (long long)LONG_MIN) ? \
- PyInt_FromLong((long)(x)) : \
- PyLong_FromLongLong((long long)(x)))
-
- #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 \
- ((PyObject *(*)(Py_ssize_t[]))_cffi_exports[12])
- #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];
- static PyObject *_cffi_types, *_cffi_VerificationError;
-
- static int _cffi_setup_custom(PyObject *lib); /* forward */
-
- 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;
- Py_INCREF(_cffi_types);
- Py_INCREF(_cffi_VerificationError);
- if (_cffi_setup_custom(library) < 0)
- return NULL;
- return PyBool_FromLong(was_alive);
- }
-
- union _cffi_union_alignment_u {
- unsigned char m_char;
- unsigned short m_short;
- unsigned int m_int;
- unsigned long m_long;
- unsigned long long m_longlong;
- float m_float;
- double m_double;
- long double m_longdouble;
- };
-
- struct _cffi_freeme_s {
- struct _cffi_freeme_s *next;
- union _cffi_union_alignment_u alignment;
- };
-
- #ifdef __GNUC__
- __attribute__((unused))
- #endif
- static int _cffi_convert_array_argument(CTypeDescrObject *ctptr, PyObject *arg,
- char **output_data, Py_ssize_t datasize,
- struct _cffi_freeme_s **freeme)
- {
- char *p;
- if (datasize < 0)
- return -1;
-
- p = *output_data;
- if (p == NULL) {
- struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc(
- offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize);
- if (fp == NULL)
- return -1;
- fp->next = *freeme;
- *freeme = fp;
- p = *output_data = (char *)&fp->alignment;
- }
- memset((void *)p, 0, (size_t)datasize);
- return _cffi_convert_array_from_object(p, ctptr, arg);
- }
-
- #ifdef __GNUC__
- __attribute__((unused))
- #endif
- static void _cffi_free_array_arguments(struct _cffi_freeme_s *freeme)
- {
- do {
- void *p = (void *)freeme;
- freeme = freeme->next;
- PyObject_Free(p);
- } while (freeme != NULL);
- }
-
- static int _cffi_init(void)
- {
- PyObject *module, *c_api_object = NULL;
-
- module = PyImport_ImportModule("_cffi_backend");
- if (module == NULL)
- goto failure;
-
- c_api_object = PyObject_GetAttrString(module, "_C_API");
- if (c_api_object == NULL)
- goto failure;
- if (!PyCapsule_CheckExact(c_api_object)) {
- PyErr_SetNone(PyExc_ImportError);
- goto failure;
- }
- memcpy(_cffi_exports, PyCapsule_GetPointer(c_api_object, "cffi"),
- _CFFI_NUM_EXPORTS * sizeof(void *));
-
- Py_DECREF(module);
- Py_DECREF(c_api_object);
- return 0;
-
- failure:
- Py_XDECREF(module);
- Py_XDECREF(c_api_object);
- return -1;
- }
-
- #define _cffi_type(num) ((CTypeDescrObject *)PyList_GET_ITEM(_cffi_types, num))
-
- /**********/
- '''
|