vengine_cpy.py 43 KB

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