Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

vengine_cpy.py 42KB

1 year ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076
  1. #
  2. # DEPRECATED: implementation for ffi.verify()
  3. #
  4. import sys, imp
  5. from . import model
  6. from .error import VerificationError
  7. class VCPythonEngine(object):
  8. _class_key = 'x'
  9. _gen_python_module = True
  10. def __init__(self, verifier):
  11. self.verifier = verifier
  12. self.ffi = verifier.ffi
  13. self._struct_pending_verification = {}
  14. self._types_of_builtin_functions = {}
  15. def patch_extension_kwds(self, kwds):
  16. pass
  17. def find_module(self, module_name, path, so_suffixes):
  18. try:
  19. f, filename, descr = imp.find_module(module_name, path)
  20. except ImportError:
  21. return None
  22. if f is not None:
  23. f.close()
  24. # Note that after a setuptools installation, there are both .py
  25. # and .so files with the same basename. The code here relies on
  26. # imp.find_module() locating the .so in priority.
  27. if descr[0] not in so_suffixes:
  28. return None
  29. return filename
  30. def collect_types(self):
  31. self._typesdict = {}
  32. self._generate("collecttype")
  33. def _prnt(self, what=''):
  34. self._f.write(what + '\n')
  35. def _gettypenum(self, type):
  36. # a KeyError here is a bug. please report it! :-)
  37. return self._typesdict[type]
  38. def _do_collect_type(self, tp):
  39. if ((not isinstance(tp, model.PrimitiveType)
  40. or tp.name == 'long double')
  41. and tp not in self._typesdict):
  42. num = len(self._typesdict)
  43. self._typesdict[tp] = num
  44. def write_source_to_f(self):
  45. self.collect_types()
  46. #
  47. # The new module will have a _cffi_setup() function that receives
  48. # objects from the ffi world, and that calls some setup code in
  49. # the module. This setup code is split in several independent
  50. # functions, e.g. one per constant. The functions are "chained"
  51. # by ending in a tail call to each other.
  52. #
  53. # This is further split in two chained lists, depending on if we
  54. # can do it at import-time or if we must wait for _cffi_setup() to
  55. # provide us with the <ctype> objects. This is needed because we
  56. # need the values of the enum constants in order to build the
  57. # <ctype 'enum'> that we may have to pass to _cffi_setup().
  58. #
  59. # The following two 'chained_list_constants' items contains
  60. # the head of these two chained lists, as a string that gives the
  61. # call to do, if any.
  62. self._chained_list_constants = ['((void)lib,0)', '((void)lib,0)']
  63. #
  64. prnt = self._prnt
  65. # first paste some standard set of lines that are mostly '#define'
  66. prnt(cffimod_header)
  67. prnt()
  68. # then paste the C source given by the user, verbatim.
  69. prnt(self.verifier.preamble)
  70. prnt()
  71. #
  72. # call generate_cpy_xxx_decl(), for every xxx found from
  73. # ffi._parser._declarations. This generates all the functions.
  74. self._generate("decl")
  75. #
  76. # implement the function _cffi_setup_custom() as calling the
  77. # head of the chained list.
  78. self._generate_setup_custom()
  79. prnt()
  80. #
  81. # produce the method table, including the entries for the
  82. # generated Python->C function wrappers, which are done
  83. # by generate_cpy_function_method().
  84. prnt('static PyMethodDef _cffi_methods[] = {')
  85. self._generate("method")
  86. prnt(' {"_cffi_setup", _cffi_setup, METH_VARARGS, NULL},')
  87. prnt(' {NULL, NULL, 0, NULL} /* Sentinel */')
  88. prnt('};')
  89. prnt()
  90. #
  91. # standard init.
  92. modname = self.verifier.get_module_name()
  93. constants = self._chained_list_constants[False]
  94. prnt('#if PY_MAJOR_VERSION >= 3')
  95. prnt()
  96. prnt('static struct PyModuleDef _cffi_module_def = {')
  97. prnt(' PyModuleDef_HEAD_INIT,')
  98. prnt(' "%s",' % modname)
  99. prnt(' NULL,')
  100. prnt(' -1,')
  101. prnt(' _cffi_methods,')
  102. prnt(' NULL, NULL, NULL, NULL')
  103. prnt('};')
  104. prnt()
  105. prnt('PyMODINIT_FUNC')
  106. prnt('PyInit_%s(void)' % modname)
  107. prnt('{')
  108. prnt(' PyObject *lib;')
  109. prnt(' lib = PyModule_Create(&_cffi_module_def);')
  110. prnt(' if (lib == NULL)')
  111. prnt(' return NULL;')
  112. prnt(' if (%s < 0 || _cffi_init() < 0) {' % (constants,))
  113. prnt(' Py_DECREF(lib);')
  114. prnt(' return NULL;')
  115. prnt(' }')
  116. prnt(' return lib;')
  117. prnt('}')
  118. prnt()
  119. prnt('#else')
  120. prnt()
  121. prnt('PyMODINIT_FUNC')
  122. prnt('init%s(void)' % modname)
  123. prnt('{')
  124. prnt(' PyObject *lib;')
  125. prnt(' lib = Py_InitModule("%s", _cffi_methods);' % modname)
  126. prnt(' if (lib == NULL)')
  127. prnt(' return;')
  128. prnt(' if (%s < 0 || _cffi_init() < 0)' % (constants,))
  129. prnt(' return;')
  130. prnt(' return;')
  131. prnt('}')
  132. prnt()
  133. prnt('#endif')
  134. def load_library(self, flags=None):
  135. # XXX review all usages of 'self' here!
  136. # import it as a new extension module
  137. imp.acquire_lock()
  138. try:
  139. if hasattr(sys, "getdlopenflags"):
  140. previous_flags = sys.getdlopenflags()
  141. try:
  142. if hasattr(sys, "setdlopenflags") and flags is not None:
  143. sys.setdlopenflags(flags)
  144. module = imp.load_dynamic(self.verifier.get_module_name(),
  145. self.verifier.modulefilename)
  146. except ImportError as e:
  147. error = "importing %r: %s" % (self.verifier.modulefilename, e)
  148. raise VerificationError(error)
  149. finally:
  150. if hasattr(sys, "setdlopenflags"):
  151. sys.setdlopenflags(previous_flags)
  152. finally:
  153. imp.release_lock()
  154. #
  155. # call loading_cpy_struct() to get the struct layout inferred by
  156. # the C compiler
  157. self._load(module, 'loading')
  158. #
  159. # the C code will need the <ctype> objects. Collect them in
  160. # order in a list.
  161. revmapping = dict([(value, key)
  162. for (key, value) in self._typesdict.items()])
  163. lst = [revmapping[i] for i in range(len(revmapping))]
  164. lst = list(map(self.ffi._get_cached_btype, lst))
  165. #
  166. # build the FFILibrary class and instance and call _cffi_setup().
  167. # this will set up some fields like '_cffi_types', and only then
  168. # it will invoke the chained list of functions that will really
  169. # build (notably) the constant objects, as <cdata> if they are
  170. # pointers, and store them as attributes on the 'library' object.
  171. class FFILibrary(object):
  172. _cffi_python_module = module
  173. _cffi_ffi = self.ffi
  174. _cffi_dir = []
  175. def __dir__(self):
  176. return FFILibrary._cffi_dir + list(self.__dict__)
  177. library = FFILibrary()
  178. if module._cffi_setup(lst, VerificationError, library):
  179. import warnings
  180. warnings.warn("reimporting %r might overwrite older definitions"
  181. % (self.verifier.get_module_name()))
  182. #
  183. # finally, call the loaded_cpy_xxx() functions. This will perform
  184. # the final adjustments, like copying the Python->C wrapper
  185. # functions from the module to the 'library' object, and setting
  186. # up the FFILibrary class with properties for the global C variables.
  187. self._load(module, 'loaded', library=library)
  188. module._cffi_original_ffi = self.ffi
  189. module._cffi_types_of_builtin_funcs = self._types_of_builtin_functions
  190. return library
  191. def _get_declarations(self):
  192. lst = [(key, tp) for (key, (tp, qual)) in
  193. self.ffi._parser._declarations.items()]
  194. lst.sort()
  195. return lst
  196. def _generate(self, step_name):
  197. for name, tp in self._get_declarations():
  198. kind, realname = name.split(' ', 1)
  199. try:
  200. method = getattr(self, '_generate_cpy_%s_%s' % (kind,
  201. step_name))
  202. except AttributeError:
  203. raise VerificationError(
  204. "not implemented in verify(): %r" % name)
  205. try:
  206. method(tp, realname)
  207. except Exception as e:
  208. model.attach_exception_info(e, name)
  209. raise
  210. def _load(self, module, step_name, **kwds):
  211. for name, tp in self._get_declarations():
  212. kind, realname = name.split(' ', 1)
  213. method = getattr(self, '_%s_cpy_%s' % (step_name, kind))
  214. try:
  215. method(tp, realname, module, **kwds)
  216. except Exception as e:
  217. model.attach_exception_info(e, name)
  218. raise
  219. def _generate_nothing(self, tp, name):
  220. pass
  221. def _loaded_noop(self, tp, name, module, **kwds):
  222. pass
  223. # ----------
  224. def _convert_funcarg_to_c(self, tp, fromvar, tovar, errcode):
  225. extraarg = ''
  226. if isinstance(tp, model.PrimitiveType):
  227. if tp.is_integer_type() and tp.name != '_Bool':
  228. converter = '_cffi_to_c_int'
  229. extraarg = ', %s' % tp.name
  230. else:
  231. converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''),
  232. tp.name.replace(' ', '_'))
  233. errvalue = '-1'
  234. #
  235. elif isinstance(tp, model.PointerType):
  236. self._convert_funcarg_to_c_ptr_or_array(tp, fromvar,
  237. tovar, errcode)
  238. return
  239. #
  240. elif isinstance(tp, (model.StructOrUnion, model.EnumType)):
  241. # a struct (not a struct pointer) as a function argument
  242. self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)'
  243. % (tovar, self._gettypenum(tp), fromvar))
  244. self._prnt(' %s;' % errcode)
  245. return
  246. #
  247. elif isinstance(tp, model.FunctionPtrType):
  248. converter = '(%s)_cffi_to_c_pointer' % tp.get_c_name('')
  249. extraarg = ', _cffi_type(%d)' % self._gettypenum(tp)
  250. errvalue = 'NULL'
  251. #
  252. else:
  253. raise NotImplementedError(tp)
  254. #
  255. self._prnt(' %s = %s(%s%s);' % (tovar, converter, fromvar, extraarg))
  256. self._prnt(' if (%s == (%s)%s && PyErr_Occurred())' % (
  257. tovar, tp.get_c_name(''), errvalue))
  258. self._prnt(' %s;' % errcode)
  259. def _extra_local_variables(self, tp, localvars, freelines):
  260. if isinstance(tp, model.PointerType):
  261. localvars.add('Py_ssize_t datasize')
  262. localvars.add('struct _cffi_freeme_s *large_args_free = NULL')
  263. freelines.add('if (large_args_free != NULL)'
  264. ' _cffi_free_array_arguments(large_args_free);')
  265. def _convert_funcarg_to_c_ptr_or_array(self, tp, fromvar, tovar, errcode):
  266. self._prnt(' datasize = _cffi_prepare_pointer_call_argument(')
  267. self._prnt(' _cffi_type(%d), %s, (char **)&%s);' % (
  268. self._gettypenum(tp), fromvar, tovar))
  269. self._prnt(' if (datasize != 0) {')
  270. self._prnt(' %s = ((size_t)datasize) <= 640 ? '
  271. 'alloca((size_t)datasize) : NULL;' % (tovar,))
  272. self._prnt(' if (_cffi_convert_array_argument(_cffi_type(%d), %s, '
  273. '(char **)&%s,' % (self._gettypenum(tp), fromvar, tovar))
  274. self._prnt(' datasize, &large_args_free) < 0)')
  275. self._prnt(' %s;' % errcode)
  276. self._prnt(' }')
  277. def _convert_expr_from_c(self, tp, var, context):
  278. if isinstance(tp, model.PrimitiveType):
  279. if tp.is_integer_type() and tp.name != '_Bool':
  280. return '_cffi_from_c_int(%s, %s)' % (var, tp.name)
  281. elif tp.name != 'long double':
  282. return '_cffi_from_c_%s(%s)' % (tp.name.replace(' ', '_'), var)
  283. else:
  284. return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % (
  285. var, self._gettypenum(tp))
  286. elif isinstance(tp, (model.PointerType, model.FunctionPtrType)):
  287. return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % (
  288. var, self._gettypenum(tp))
  289. elif isinstance(tp, model.ArrayType):
  290. return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % (
  291. var, self._gettypenum(model.PointerType(tp.item)))
  292. elif isinstance(tp, model.StructOrUnion):
  293. if tp.fldnames is None:
  294. raise TypeError("'%s' is used as %s, but is opaque" % (
  295. tp._get_c_name(), context))
  296. return '_cffi_from_c_struct((char *)&%s, _cffi_type(%d))' % (
  297. var, self._gettypenum(tp))
  298. elif isinstance(tp, model.EnumType):
  299. return '_cffi_from_c_deref((char *)&%s, _cffi_type(%d))' % (
  300. var, self._gettypenum(tp))
  301. else:
  302. raise NotImplementedError(tp)
  303. # ----------
  304. # typedefs: generates no code so far
  305. _generate_cpy_typedef_collecttype = _generate_nothing
  306. _generate_cpy_typedef_decl = _generate_nothing
  307. _generate_cpy_typedef_method = _generate_nothing
  308. _loading_cpy_typedef = _loaded_noop
  309. _loaded_cpy_typedef = _loaded_noop
  310. # ----------
  311. # function declarations
  312. def _generate_cpy_function_collecttype(self, tp, name):
  313. assert isinstance(tp, model.FunctionPtrType)
  314. if tp.ellipsis:
  315. self._do_collect_type(tp)
  316. else:
  317. # don't call _do_collect_type(tp) in this common case,
  318. # otherwise test_autofilled_struct_as_argument fails
  319. for type in tp.args:
  320. self._do_collect_type(type)
  321. self._do_collect_type(tp.result)
  322. def _generate_cpy_function_decl(self, tp, name):
  323. assert isinstance(tp, model.FunctionPtrType)
  324. if tp.ellipsis:
  325. # cannot support vararg functions better than this: check for its
  326. # exact type (including the fixed arguments), and build it as a
  327. # constant function pointer (no CPython wrapper)
  328. self._generate_cpy_const(False, name, tp)
  329. return
  330. prnt = self._prnt
  331. numargs = len(tp.args)
  332. if numargs == 0:
  333. argname = 'noarg'
  334. elif numargs == 1:
  335. argname = 'arg0'
  336. else:
  337. argname = 'args'
  338. prnt('static PyObject *')
  339. prnt('_cffi_f_%s(PyObject *self, PyObject *%s)' % (name, argname))
  340. prnt('{')
  341. #
  342. context = 'argument of %s' % name
  343. for i, type in enumerate(tp.args):
  344. prnt(' %s;' % type.get_c_name(' x%d' % i, context))
  345. #
  346. localvars = set()
  347. freelines = set()
  348. for type in tp.args:
  349. self._extra_local_variables(type, localvars, freelines)
  350. for decl in sorted(localvars):
  351. prnt(' %s;' % (decl,))
  352. #
  353. if not isinstance(tp.result, model.VoidType):
  354. result_code = 'result = '
  355. context = 'result of %s' % name
  356. prnt(' %s;' % tp.result.get_c_name(' result', context))
  357. prnt(' PyObject *pyresult;')
  358. else:
  359. result_code = ''
  360. #
  361. if len(tp.args) > 1:
  362. rng = range(len(tp.args))
  363. for i in rng:
  364. prnt(' PyObject *arg%d;' % i)
  365. prnt()
  366. prnt(' if (!PyArg_ParseTuple(args, "%s:%s", %s))' % (
  367. 'O' * numargs, name, ', '.join(['&arg%d' % i for i in rng])))
  368. prnt(' return NULL;')
  369. prnt()
  370. #
  371. for i, type in enumerate(tp.args):
  372. self._convert_funcarg_to_c(type, 'arg%d' % i, 'x%d' % i,
  373. 'return NULL')
  374. prnt()
  375. #
  376. prnt(' Py_BEGIN_ALLOW_THREADS')
  377. prnt(' _cffi_restore_errno();')
  378. prnt(' { %s%s(%s); }' % (
  379. result_code, name,
  380. ', '.join(['x%d' % i for i in range(len(tp.args))])))
  381. prnt(' _cffi_save_errno();')
  382. prnt(' Py_END_ALLOW_THREADS')
  383. prnt()
  384. #
  385. prnt(' (void)self; /* unused */')
  386. if numargs == 0:
  387. prnt(' (void)noarg; /* unused */')
  388. if result_code:
  389. prnt(' pyresult = %s;' %
  390. self._convert_expr_from_c(tp.result, 'result', 'result type'))
  391. for freeline in freelines:
  392. prnt(' ' + freeline)
  393. prnt(' return pyresult;')
  394. else:
  395. for freeline in freelines:
  396. prnt(' ' + freeline)
  397. prnt(' Py_INCREF(Py_None);')
  398. prnt(' return Py_None;')
  399. prnt('}')
  400. prnt()
  401. def _generate_cpy_function_method(self, tp, name):
  402. if tp.ellipsis:
  403. return
  404. numargs = len(tp.args)
  405. if numargs == 0:
  406. meth = 'METH_NOARGS'
  407. elif numargs == 1:
  408. meth = 'METH_O'
  409. else:
  410. meth = 'METH_VARARGS'
  411. self._prnt(' {"%s", _cffi_f_%s, %s, NULL},' % (name, name, meth))
  412. _loading_cpy_function = _loaded_noop
  413. def _loaded_cpy_function(self, tp, name, module, library):
  414. if tp.ellipsis:
  415. return
  416. func = getattr(module, name)
  417. setattr(library, name, func)
  418. self._types_of_builtin_functions[func] = tp
  419. # ----------
  420. # named structs
  421. _generate_cpy_struct_collecttype = _generate_nothing
  422. def _generate_cpy_struct_decl(self, tp, name):
  423. assert name == tp.name
  424. self._generate_struct_or_union_decl(tp, 'struct', name)
  425. def _generate_cpy_struct_method(self, tp, name):
  426. self._generate_struct_or_union_method(tp, 'struct', name)
  427. def _loading_cpy_struct(self, tp, name, module):
  428. self._loading_struct_or_union(tp, 'struct', name, module)
  429. def _loaded_cpy_struct(self, tp, name, module, **kwds):
  430. self._loaded_struct_or_union(tp)
  431. _generate_cpy_union_collecttype = _generate_nothing
  432. def _generate_cpy_union_decl(self, tp, name):
  433. assert name == tp.name
  434. self._generate_struct_or_union_decl(tp, 'union', name)
  435. def _generate_cpy_union_method(self, tp, name):
  436. self._generate_struct_or_union_method(tp, 'union', name)
  437. def _loading_cpy_union(self, tp, name, module):
  438. self._loading_struct_or_union(tp, 'union', name, module)
  439. def _loaded_cpy_union(self, tp, name, module, **kwds):
  440. self._loaded_struct_or_union(tp)
  441. def _generate_struct_or_union_decl(self, tp, prefix, name):
  442. if tp.fldnames is None:
  443. return # nothing to do with opaque structs
  444. checkfuncname = '_cffi_check_%s_%s' % (prefix, name)
  445. layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name)
  446. cname = ('%s %s' % (prefix, name)).strip()
  447. #
  448. prnt = self._prnt
  449. prnt('static void %s(%s *p)' % (checkfuncname, cname))
  450. prnt('{')
  451. prnt(' /* only to generate compile-time warnings or errors */')
  452. prnt(' (void)p;')
  453. for fname, ftype, fbitsize, fqual in tp.enumfields():
  454. if (isinstance(ftype, model.PrimitiveType)
  455. and ftype.is_integer_type()) or fbitsize >= 0:
  456. # accept all integers, but complain on float or double
  457. prnt(' (void)((p->%s) << 1);' % fname)
  458. else:
  459. # only accept exactly the type declared.
  460. try:
  461. prnt(' { %s = &p->%s; (void)tmp; }' % (
  462. ftype.get_c_name('*tmp', 'field %r'%fname, quals=fqual),
  463. fname))
  464. except VerificationError as e:
  465. prnt(' /* %s */' % str(e)) # cannot verify it, ignore
  466. prnt('}')
  467. prnt('static PyObject *')
  468. prnt('%s(PyObject *self, PyObject *noarg)' % (layoutfuncname,))
  469. prnt('{')
  470. prnt(' struct _cffi_aligncheck { char x; %s y; };' % cname)
  471. prnt(' static Py_ssize_t nums[] = {')
  472. prnt(' sizeof(%s),' % cname)
  473. prnt(' offsetof(struct _cffi_aligncheck, y),')
  474. for fname, ftype, fbitsize, fqual in tp.enumfields():
  475. if fbitsize >= 0:
  476. continue # xxx ignore fbitsize for now
  477. prnt(' offsetof(%s, %s),' % (cname, fname))
  478. if isinstance(ftype, model.ArrayType) and ftype.length is None:
  479. prnt(' 0, /* %s */' % ftype._get_c_name())
  480. else:
  481. prnt(' sizeof(((%s *)0)->%s),' % (cname, fname))
  482. prnt(' -1')
  483. prnt(' };')
  484. prnt(' (void)self; /* unused */')
  485. prnt(' (void)noarg; /* unused */')
  486. prnt(' return _cffi_get_struct_layout(nums);')
  487. prnt(' /* the next line is not executed, but compiled */')
  488. prnt(' %s(0);' % (checkfuncname,))
  489. prnt('}')
  490. prnt()
  491. def _generate_struct_or_union_method(self, tp, prefix, name):
  492. if tp.fldnames is None:
  493. return # nothing to do with opaque structs
  494. layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name)
  495. self._prnt(' {"%s", %s, METH_NOARGS, NULL},' % (layoutfuncname,
  496. layoutfuncname))
  497. def _loading_struct_or_union(self, tp, prefix, name, module):
  498. if tp.fldnames is None:
  499. return # nothing to do with opaque structs
  500. layoutfuncname = '_cffi_layout_%s_%s' % (prefix, name)
  501. #
  502. function = getattr(module, layoutfuncname)
  503. layout = function()
  504. if isinstance(tp, model.StructOrUnion) and tp.partial:
  505. # use the function()'s sizes and offsets to guide the
  506. # layout of the struct
  507. totalsize = layout[0]
  508. totalalignment = layout[1]
  509. fieldofs = layout[2::2]
  510. fieldsize = layout[3::2]
  511. tp.force_flatten()
  512. assert len(fieldofs) == len(fieldsize) == len(tp.fldnames)
  513. tp.fixedlayout = fieldofs, fieldsize, totalsize, totalalignment
  514. else:
  515. cname = ('%s %s' % (prefix, name)).strip()
  516. self._struct_pending_verification[tp] = layout, cname
  517. def _loaded_struct_or_union(self, tp):
  518. if tp.fldnames is None:
  519. return # nothing to do with opaque structs
  520. self.ffi._get_cached_btype(tp) # force 'fixedlayout' to be considered
  521. if tp in self._struct_pending_verification:
  522. # check that the layout sizes and offsets match the real ones
  523. def check(realvalue, expectedvalue, msg):
  524. if realvalue != expectedvalue:
  525. raise VerificationError(
  526. "%s (we have %d, but C compiler says %d)"
  527. % (msg, expectedvalue, realvalue))
  528. ffi = self.ffi
  529. BStruct = ffi._get_cached_btype(tp)
  530. layout, cname = self._struct_pending_verification.pop(tp)
  531. check(layout[0], ffi.sizeof(BStruct), "wrong total size")
  532. check(layout[1], ffi.alignof(BStruct), "wrong total alignment")
  533. i = 2
  534. for fname, ftype, fbitsize, fqual in tp.enumfields():
  535. if fbitsize >= 0:
  536. continue # xxx ignore fbitsize for now
  537. check(layout[i], ffi.offsetof(BStruct, fname),
  538. "wrong offset for field %r" % (fname,))
  539. if layout[i+1] != 0:
  540. BField = ffi._get_cached_btype(ftype)
  541. check(layout[i+1], ffi.sizeof(BField),
  542. "wrong size for field %r" % (fname,))
  543. i += 2
  544. assert i == len(layout)
  545. # ----------
  546. # 'anonymous' declarations. These are produced for anonymous structs
  547. # or unions; the 'name' is obtained by a typedef.
  548. _generate_cpy_anonymous_collecttype = _generate_nothing
  549. def _generate_cpy_anonymous_decl(self, tp, name):
  550. if isinstance(tp, model.EnumType):
  551. self._generate_cpy_enum_decl(tp, name, '')
  552. else:
  553. self._generate_struct_or_union_decl(tp, '', name)
  554. def _generate_cpy_anonymous_method(self, tp, name):
  555. if not isinstance(tp, model.EnumType):
  556. self._generate_struct_or_union_method(tp, '', name)
  557. def _loading_cpy_anonymous(self, tp, name, module):
  558. if isinstance(tp, model.EnumType):
  559. self._loading_cpy_enum(tp, name, module)
  560. else:
  561. self._loading_struct_or_union(tp, '', name, module)
  562. def _loaded_cpy_anonymous(self, tp, name, module, **kwds):
  563. if isinstance(tp, model.EnumType):
  564. self._loaded_cpy_enum(tp, name, module, **kwds)
  565. else:
  566. self._loaded_struct_or_union(tp)
  567. # ----------
  568. # constants, likely declared with '#define'
  569. def _generate_cpy_const(self, is_int, name, tp=None, category='const',
  570. vartp=None, delayed=True, size_too=False,
  571. check_value=None):
  572. prnt = self._prnt
  573. funcname = '_cffi_%s_%s' % (category, name)
  574. prnt('static int %s(PyObject *lib)' % funcname)
  575. prnt('{')
  576. prnt(' PyObject *o;')
  577. prnt(' int res;')
  578. if not is_int:
  579. prnt(' %s;' % (vartp or tp).get_c_name(' i', name))
  580. else:
  581. assert category == 'const'
  582. #
  583. if check_value is not None:
  584. self._check_int_constant_value(name, check_value)
  585. #
  586. if not is_int:
  587. if category == 'var':
  588. realexpr = '&' + name
  589. else:
  590. realexpr = name
  591. prnt(' i = (%s);' % (realexpr,))
  592. prnt(' o = %s;' % (self._convert_expr_from_c(tp, 'i',
  593. 'variable type'),))
  594. assert delayed
  595. else:
  596. prnt(' o = _cffi_from_c_int_const(%s);' % name)
  597. prnt(' if (o == NULL)')
  598. prnt(' return -1;')
  599. if size_too:
  600. prnt(' {')
  601. prnt(' PyObject *o1 = o;')
  602. prnt(' o = Py_BuildValue("On", o1, (Py_ssize_t)sizeof(%s));'
  603. % (name,))
  604. prnt(' Py_DECREF(o1);')
  605. prnt(' if (o == NULL)')
  606. prnt(' return -1;')
  607. prnt(' }')
  608. prnt(' res = PyObject_SetAttrString(lib, "%s", o);' % name)
  609. prnt(' Py_DECREF(o);')
  610. prnt(' if (res < 0)')
  611. prnt(' return -1;')
  612. prnt(' return %s;' % self._chained_list_constants[delayed])
  613. self._chained_list_constants[delayed] = funcname + '(lib)'
  614. prnt('}')
  615. prnt()
  616. def _generate_cpy_constant_collecttype(self, tp, name):
  617. is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
  618. if not is_int:
  619. self._do_collect_type(tp)
  620. def _generate_cpy_constant_decl(self, tp, name):
  621. is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
  622. self._generate_cpy_const(is_int, name, tp)
  623. _generate_cpy_constant_method = _generate_nothing
  624. _loading_cpy_constant = _loaded_noop
  625. _loaded_cpy_constant = _loaded_noop
  626. # ----------
  627. # enums
  628. def _check_int_constant_value(self, name, value, err_prefix=''):
  629. prnt = self._prnt
  630. if value <= 0:
  631. prnt(' if ((%s) > 0 || (long)(%s) != %dL) {' % (
  632. name, name, value))
  633. else:
  634. prnt(' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {' % (
  635. name, name, value))
  636. prnt(' char buf[64];')
  637. prnt(' if ((%s) <= 0)' % name)
  638. prnt(' snprintf(buf, 63, "%%ld", (long)(%s));' % name)
  639. prnt(' else')
  640. prnt(' snprintf(buf, 63, "%%lu", (unsigned long)(%s));' %
  641. name)
  642. prnt(' PyErr_Format(_cffi_VerificationError,')
  643. prnt(' "%s%s has the real value %s, not %s",')
  644. prnt(' "%s", "%s", buf, "%d");' % (
  645. err_prefix, name, value))
  646. prnt(' return -1;')
  647. prnt(' }')
  648. def _enum_funcname(self, prefix, name):
  649. # "$enum_$1" => "___D_enum____D_1"
  650. name = name.replace('$', '___D_')
  651. return '_cffi_e_%s_%s' % (prefix, name)
  652. def _generate_cpy_enum_decl(self, tp, name, prefix='enum'):
  653. if tp.partial:
  654. for enumerator in tp.enumerators:
  655. self._generate_cpy_const(True, enumerator, delayed=False)
  656. return
  657. #
  658. funcname = self._enum_funcname(prefix, name)
  659. prnt = self._prnt
  660. prnt('static int %s(PyObject *lib)' % funcname)
  661. prnt('{')
  662. for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
  663. self._check_int_constant_value(enumerator, enumvalue,
  664. "enum %s: " % name)
  665. prnt(' return %s;' % self._chained_list_constants[True])
  666. self._chained_list_constants[True] = funcname + '(lib)'
  667. prnt('}')
  668. prnt()
  669. _generate_cpy_enum_collecttype = _generate_nothing
  670. _generate_cpy_enum_method = _generate_nothing
  671. def _loading_cpy_enum(self, tp, name, module):
  672. if tp.partial:
  673. enumvalues = [getattr(module, enumerator)
  674. for enumerator in tp.enumerators]
  675. tp.enumvalues = tuple(enumvalues)
  676. tp.partial_resolved = True
  677. def _loaded_cpy_enum(self, tp, name, module, library):
  678. for enumerator, enumvalue in zip(tp.enumerators, tp.enumvalues):
  679. setattr(library, enumerator, enumvalue)
  680. # ----------
  681. # macros: for now only for integers
  682. def _generate_cpy_macro_decl(self, tp, name):
  683. if tp == '...':
  684. check_value = None
  685. else:
  686. check_value = tp # an integer
  687. self._generate_cpy_const(True, name, check_value=check_value)
  688. _generate_cpy_macro_collecttype = _generate_nothing
  689. _generate_cpy_macro_method = _generate_nothing
  690. _loading_cpy_macro = _loaded_noop
  691. _loaded_cpy_macro = _loaded_noop
  692. # ----------
  693. # global variables
  694. def _generate_cpy_variable_collecttype(self, tp, name):
  695. if isinstance(tp, model.ArrayType):
  696. tp_ptr = model.PointerType(tp.item)
  697. else:
  698. tp_ptr = model.PointerType(tp)
  699. self._do_collect_type(tp_ptr)
  700. def _generate_cpy_variable_decl(self, tp, name):
  701. if isinstance(tp, model.ArrayType):
  702. tp_ptr = model.PointerType(tp.item)
  703. self._generate_cpy_const(False, name, tp, vartp=tp_ptr,
  704. size_too = tp.length_is_unknown())
  705. else:
  706. tp_ptr = model.PointerType(tp)
  707. self._generate_cpy_const(False, name, tp_ptr, category='var')
  708. _generate_cpy_variable_method = _generate_nothing
  709. _loading_cpy_variable = _loaded_noop
  710. def _loaded_cpy_variable(self, tp, name, module, library):
  711. value = getattr(library, name)
  712. if isinstance(tp, model.ArrayType): # int a[5] is "constant" in the
  713. # sense that "a=..." is forbidden
  714. if tp.length_is_unknown():
  715. assert isinstance(value, tuple)
  716. (value, size) = value
  717. BItemType = self.ffi._get_cached_btype(tp.item)
  718. length, rest = divmod(size, self.ffi.sizeof(BItemType))
  719. if rest != 0:
  720. raise VerificationError(
  721. "bad size: %r does not seem to be an array of %s" %
  722. (name, tp.item))
  723. tp = tp.resolve_length(length)
  724. # 'value' is a <cdata 'type *'> which we have to replace with
  725. # a <cdata 'type[N]'> if the N is actually known
  726. if tp.length is not None:
  727. BArray = self.ffi._get_cached_btype(tp)
  728. value = self.ffi.cast(BArray, value)
  729. setattr(library, name, value)
  730. return
  731. # remove ptr=<cdata 'int *'> from the library instance, and replace
  732. # it by a property on the class, which reads/writes into ptr[0].
  733. ptr = value
  734. delattr(library, name)
  735. def getter(library):
  736. return ptr[0]
  737. def setter(library, value):
  738. ptr[0] = value
  739. setattr(type(library), name, property(getter, setter))
  740. type(library)._cffi_dir.append(name)
  741. # ----------
  742. def _generate_setup_custom(self):
  743. prnt = self._prnt
  744. prnt('static int _cffi_setup_custom(PyObject *lib)')
  745. prnt('{')
  746. prnt(' return %s;' % self._chained_list_constants[True])
  747. prnt('}')
  748. cffimod_header = r'''
  749. #include <Python.h>
  750. #include <stddef.h>
  751. /* this block of #ifs should be kept exactly identical between
  752. c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py
  753. and cffi/_cffi_include.h */
  754. #if defined(_MSC_VER)
  755. # include <malloc.h> /* for alloca() */
  756. # if _MSC_VER < 1600 /* MSVC < 2010 */
  757. typedef __int8 int8_t;
  758. typedef __int16 int16_t;
  759. typedef __int32 int32_t;
  760. typedef __int64 int64_t;
  761. typedef unsigned __int8 uint8_t;
  762. typedef unsigned __int16 uint16_t;
  763. typedef unsigned __int32 uint32_t;
  764. typedef unsigned __int64 uint64_t;
  765. typedef __int8 int_least8_t;
  766. typedef __int16 int_least16_t;
  767. typedef __int32 int_least32_t;
  768. typedef __int64 int_least64_t;
  769. typedef unsigned __int8 uint_least8_t;
  770. typedef unsigned __int16 uint_least16_t;
  771. typedef unsigned __int32 uint_least32_t;
  772. typedef unsigned __int64 uint_least64_t;
  773. typedef __int8 int_fast8_t;
  774. typedef __int16 int_fast16_t;
  775. typedef __int32 int_fast32_t;
  776. typedef __int64 int_fast64_t;
  777. typedef unsigned __int8 uint_fast8_t;
  778. typedef unsigned __int16 uint_fast16_t;
  779. typedef unsigned __int32 uint_fast32_t;
  780. typedef unsigned __int64 uint_fast64_t;
  781. typedef __int64 intmax_t;
  782. typedef unsigned __int64 uintmax_t;
  783. # else
  784. # include <stdint.h>
  785. # endif
  786. # if _MSC_VER < 1800 /* MSVC < 2013 */
  787. # ifndef __cplusplus
  788. typedef unsigned char _Bool;
  789. # endif
  790. # endif
  791. #else
  792. # include <stdint.h>
  793. # if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux)
  794. # include <alloca.h>
  795. # endif
  796. #endif
  797. #if PY_MAJOR_VERSION < 3
  798. # undef PyCapsule_CheckExact
  799. # undef PyCapsule_GetPointer
  800. # define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule))
  801. # define PyCapsule_GetPointer(capsule, name) \
  802. (PyCObject_AsVoidPtr(capsule))
  803. #endif
  804. #if PY_MAJOR_VERSION >= 3
  805. # define PyInt_FromLong PyLong_FromLong
  806. #endif
  807. #define _cffi_from_c_double PyFloat_FromDouble
  808. #define _cffi_from_c_float PyFloat_FromDouble
  809. #define _cffi_from_c_long PyInt_FromLong
  810. #define _cffi_from_c_ulong PyLong_FromUnsignedLong
  811. #define _cffi_from_c_longlong PyLong_FromLongLong
  812. #define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong
  813. #define _cffi_from_c__Bool PyBool_FromLong
  814. #define _cffi_to_c_double PyFloat_AsDouble
  815. #define _cffi_to_c_float PyFloat_AsDouble
  816. #define _cffi_from_c_int_const(x) \
  817. (((x) > 0) ? \
  818. ((unsigned long long)(x) <= (unsigned long long)LONG_MAX) ? \
  819. PyInt_FromLong((long)(x)) : \
  820. PyLong_FromUnsignedLongLong((unsigned long long)(x)) : \
  821. ((long long)(x) >= (long long)LONG_MIN) ? \
  822. PyInt_FromLong((long)(x)) : \
  823. PyLong_FromLongLong((long long)(x)))
  824. #define _cffi_from_c_int(x, type) \
  825. (((type)-1) > 0 ? /* unsigned */ \
  826. (sizeof(type) < sizeof(long) ? \
  827. PyInt_FromLong((long)x) : \
  828. sizeof(type) == sizeof(long) ? \
  829. PyLong_FromUnsignedLong((unsigned long)x) : \
  830. PyLong_FromUnsignedLongLong((unsigned long long)x)) : \
  831. (sizeof(type) <= sizeof(long) ? \
  832. PyInt_FromLong((long)x) : \
  833. PyLong_FromLongLong((long long)x)))
  834. #define _cffi_to_c_int(o, type) \
  835. ((type)( \
  836. sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \
  837. : (type)_cffi_to_c_i8(o)) : \
  838. sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \
  839. : (type)_cffi_to_c_i16(o)) : \
  840. sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \
  841. : (type)_cffi_to_c_i32(o)) : \
  842. sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \
  843. : (type)_cffi_to_c_i64(o)) : \
  844. (Py_FatalError("unsupported size for type " #type), (type)0)))
  845. #define _cffi_to_c_i8 \
  846. ((int(*)(PyObject *))_cffi_exports[1])
  847. #define _cffi_to_c_u8 \
  848. ((int(*)(PyObject *))_cffi_exports[2])
  849. #define _cffi_to_c_i16 \
  850. ((int(*)(PyObject *))_cffi_exports[3])
  851. #define _cffi_to_c_u16 \
  852. ((int(*)(PyObject *))_cffi_exports[4])
  853. #define _cffi_to_c_i32 \
  854. ((int(*)(PyObject *))_cffi_exports[5])
  855. #define _cffi_to_c_u32 \
  856. ((unsigned int(*)(PyObject *))_cffi_exports[6])
  857. #define _cffi_to_c_i64 \
  858. ((long long(*)(PyObject *))_cffi_exports[7])
  859. #define _cffi_to_c_u64 \
  860. ((unsigned long long(*)(PyObject *))_cffi_exports[8])
  861. #define _cffi_to_c_char \
  862. ((int(*)(PyObject *))_cffi_exports[9])
  863. #define _cffi_from_c_pointer \
  864. ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10])
  865. #define _cffi_to_c_pointer \
  866. ((char *(*)(PyObject *, CTypeDescrObject *))_cffi_exports[11])
  867. #define _cffi_get_struct_layout \
  868. ((PyObject *(*)(Py_ssize_t[]))_cffi_exports[12])
  869. #define _cffi_restore_errno \
  870. ((void(*)(void))_cffi_exports[13])
  871. #define _cffi_save_errno \
  872. ((void(*)(void))_cffi_exports[14])
  873. #define _cffi_from_c_char \
  874. ((PyObject *(*)(char))_cffi_exports[15])
  875. #define _cffi_from_c_deref \
  876. ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16])
  877. #define _cffi_to_c \
  878. ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17])
  879. #define _cffi_from_c_struct \
  880. ((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[18])
  881. #define _cffi_to_c_wchar_t \
  882. ((wchar_t(*)(PyObject *))_cffi_exports[19])
  883. #define _cffi_from_c_wchar_t \
  884. ((PyObject *(*)(wchar_t))_cffi_exports[20])
  885. #define _cffi_to_c_long_double \
  886. ((long double(*)(PyObject *))_cffi_exports[21])
  887. #define _cffi_to_c__Bool \
  888. ((_Bool(*)(PyObject *))_cffi_exports[22])
  889. #define _cffi_prepare_pointer_call_argument \
  890. ((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23])
  891. #define _cffi_convert_array_from_object \
  892. ((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24])
  893. #define _CFFI_NUM_EXPORTS 25
  894. typedef struct _ctypedescr CTypeDescrObject;
  895. static void *_cffi_exports[_CFFI_NUM_EXPORTS];
  896. static PyObject *_cffi_types, *_cffi_VerificationError;
  897. static int _cffi_setup_custom(PyObject *lib); /* forward */
  898. static PyObject *_cffi_setup(PyObject *self, PyObject *args)
  899. {
  900. PyObject *library;
  901. int was_alive = (_cffi_types != NULL);
  902. (void)self; /* unused */
  903. if (!PyArg_ParseTuple(args, "OOO", &_cffi_types, &_cffi_VerificationError,
  904. &library))
  905. return NULL;
  906. Py_INCREF(_cffi_types);
  907. Py_INCREF(_cffi_VerificationError);
  908. if (_cffi_setup_custom(library) < 0)
  909. return NULL;
  910. return PyBool_FromLong(was_alive);
  911. }
  912. union _cffi_union_alignment_u {
  913. unsigned char m_char;
  914. unsigned short m_short;
  915. unsigned int m_int;
  916. unsigned long m_long;
  917. unsigned long long m_longlong;
  918. float m_float;
  919. double m_double;
  920. long double m_longdouble;
  921. };
  922. struct _cffi_freeme_s {
  923. struct _cffi_freeme_s *next;
  924. union _cffi_union_alignment_u alignment;
  925. };
  926. #ifdef __GNUC__
  927. __attribute__((unused))
  928. #endif
  929. static int _cffi_convert_array_argument(CTypeDescrObject *ctptr, PyObject *arg,
  930. char **output_data, Py_ssize_t datasize,
  931. struct _cffi_freeme_s **freeme)
  932. {
  933. char *p;
  934. if (datasize < 0)
  935. return -1;
  936. p = *output_data;
  937. if (p == NULL) {
  938. struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc(
  939. offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize);
  940. if (fp == NULL)
  941. return -1;
  942. fp->next = *freeme;
  943. *freeme = fp;
  944. p = *output_data = (char *)&fp->alignment;
  945. }
  946. memset((void *)p, 0, (size_t)datasize);
  947. return _cffi_convert_array_from_object(p, ctptr, arg);
  948. }
  949. #ifdef __GNUC__
  950. __attribute__((unused))
  951. #endif
  952. static void _cffi_free_array_arguments(struct _cffi_freeme_s *freeme)
  953. {
  954. do {
  955. void *p = (void *)freeme;
  956. freeme = freeme->next;
  957. PyObject_Free(p);
  958. } while (freeme != NULL);
  959. }
  960. static int _cffi_init(void)
  961. {
  962. PyObject *module, *c_api_object = NULL;
  963. module = PyImport_ImportModule("_cffi_backend");
  964. if (module == NULL)
  965. goto failure;
  966. c_api_object = PyObject_GetAttrString(module, "_C_API");
  967. if (c_api_object == NULL)
  968. goto failure;
  969. if (!PyCapsule_CheckExact(c_api_object)) {
  970. PyErr_SetNone(PyExc_ImportError);
  971. goto failure;
  972. }
  973. memcpy(_cffi_exports, PyCapsule_GetPointer(c_api_object, "cffi"),
  974. _CFFI_NUM_EXPORTS * sizeof(void *));
  975. Py_DECREF(module);
  976. Py_DECREF(c_api_object);
  977. return 0;
  978. failure:
  979. Py_XDECREF(module);
  980. Py_XDECREF(c_api_object);
  981. return -1;
  982. }
  983. #define _cffi_type(num) ((CTypeDescrObject *)PyList_GET_ITEM(_cffi_types, num))
  984. /**********/
  985. '''