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