OLD | NEW |
(Empty) | |
| 1 # |
| 2 # Module parse tree node |
| 3 # |
| 4 |
| 5 import cython |
| 6 cython.declare(Naming=object, Options=object, PyrexTypes=object, TypeSlots=objec
t, |
| 7 error=object, warning=object, py_object_type=object, UtilityCode=
object, |
| 8 EncodedString=object) |
| 9 |
| 10 import os |
| 11 import operator |
| 12 from PyrexTypes import CPtrType |
| 13 import Future |
| 14 |
| 15 import Annotate |
| 16 import Code |
| 17 import Naming |
| 18 import Nodes |
| 19 import Options |
| 20 import TypeSlots |
| 21 import Version |
| 22 import PyrexTypes |
| 23 |
| 24 from Errors import error, warning |
| 25 from PyrexTypes import py_object_type |
| 26 from Cython.Utils import open_new_file, replace_suffix, decode_filename |
| 27 from Code import UtilityCode |
| 28 from StringEncoding import EncodedString |
| 29 |
| 30 |
| 31 |
| 32 def check_c_declarations_pxd(module_node): |
| 33 module_node.scope.check_c_classes_pxd() |
| 34 return module_node |
| 35 |
| 36 def check_c_declarations(module_node): |
| 37 module_node.scope.check_c_classes() |
| 38 module_node.scope.check_c_functions() |
| 39 return module_node |
| 40 |
| 41 class ModuleNode(Nodes.Node, Nodes.BlockNode): |
| 42 # doc string or None |
| 43 # body StatListNode |
| 44 # |
| 45 # referenced_modules [ModuleScope] |
| 46 # full_module_name string |
| 47 # |
| 48 # scope The module scope. |
| 49 # compilation_source A CompilationSource (see Main) |
| 50 # directives Top-level compiler directives |
| 51 |
| 52 child_attrs = ["body"] |
| 53 directives = None |
| 54 |
| 55 def merge_in(self, tree, scope, merge_scope=False): |
| 56 # Merges in the contents of another tree, and possibly scope. With the |
| 57 # current implementation below, this must be done right prior |
| 58 # to code generation. |
| 59 # |
| 60 # Note: This way of doing it seems strange -- I believe the |
| 61 # right concept is to split ModuleNode into a ModuleNode and a |
| 62 # CodeGenerator, and tell that CodeGenerator to generate code |
| 63 # from multiple sources. |
| 64 assert isinstance(self.body, Nodes.StatListNode) |
| 65 if isinstance(tree, Nodes.StatListNode): |
| 66 self.body.stats.extend(tree.stats) |
| 67 else: |
| 68 self.body.stats.append(tree) |
| 69 |
| 70 self.scope.utility_code_list.extend(scope.utility_code_list) |
| 71 |
| 72 def extend_if_not_in(L1, L2): |
| 73 for x in L2: |
| 74 if x not in L1: |
| 75 L1.append(x) |
| 76 |
| 77 extend_if_not_in(self.scope.include_files, scope.include_files) |
| 78 extend_if_not_in(self.scope.included_files, scope.included_files) |
| 79 extend_if_not_in(self.scope.python_include_files, |
| 80 scope.python_include_files) |
| 81 |
| 82 if merge_scope: |
| 83 # Ensure that we don't generate import code for these entries! |
| 84 for entry in scope.c_class_entries: |
| 85 entry.type.module_name = self.full_module_name |
| 86 entry.type.scope.directives["internal"] = True |
| 87 |
| 88 self.scope.merge_in(scope) |
| 89 |
| 90 def analyse_declarations(self, env): |
| 91 if not Options.docstrings: |
| 92 env.doc = self.doc = None |
| 93 elif Options.embed_pos_in_docstring: |
| 94 env.doc = EncodedString(u'File: %s (starting at line %s)' % Nodes.re
lative_position(self.pos)) |
| 95 if not self.doc is None: |
| 96 env.doc = EncodedString(env.doc + u'\n' + self.doc) |
| 97 env.doc.encoding = self.doc.encoding |
| 98 else: |
| 99 env.doc = self.doc |
| 100 env.directives = self.directives |
| 101 self.body.analyse_declarations(env) |
| 102 |
| 103 def process_implementation(self, options, result): |
| 104 env = self.scope |
| 105 env.return_type = PyrexTypes.c_void_type |
| 106 self.referenced_modules = [] |
| 107 self.find_referenced_modules(env, self.referenced_modules, {}) |
| 108 self.sort_cdef_classes(env) |
| 109 self.generate_c_code(env, options, result) |
| 110 self.generate_h_code(env, options, result) |
| 111 self.generate_api_code(env, result) |
| 112 |
| 113 def has_imported_c_functions(self): |
| 114 for module in self.referenced_modules: |
| 115 for entry in module.cfunc_entries: |
| 116 if entry.defined_in_pxd: |
| 117 return 1 |
| 118 return 0 |
| 119 |
| 120 def generate_h_code(self, env, options, result): |
| 121 def h_entries(entries, api=0, pxd=0): |
| 122 return [entry for entry in entries |
| 123 if ((entry.visibility == 'public') or |
| 124 (api and entry.api) or |
| 125 (pxd and entry.defined_in_pxd))] |
| 126 h_types = h_entries(env.type_entries, api=1) |
| 127 h_vars = h_entries(env.var_entries) |
| 128 h_funcs = h_entries(env.cfunc_entries) |
| 129 h_extension_types = h_entries(env.c_class_entries) |
| 130 if (h_types or h_vars or h_funcs or h_extension_types): |
| 131 result.h_file = replace_suffix(result.c_file, ".h") |
| 132 h_code = Code.CCodeWriter() |
| 133 Code.GlobalState(h_code, self) |
| 134 if options.generate_pxi: |
| 135 result.i_file = replace_suffix(result.c_file, ".pxi") |
| 136 i_code = Code.PyrexCodeWriter(result.i_file) |
| 137 else: |
| 138 i_code = None |
| 139 |
| 140 h_guard = Naming.h_guard_prefix + self.api_name(env) |
| 141 h_code.put_h_guard(h_guard) |
| 142 h_code.putln("") |
| 143 self.generate_type_header_code(h_types, h_code) |
| 144 if options.capi_reexport_cincludes: |
| 145 self.generate_includes(env, [], h_code) |
| 146 h_code.putln("") |
| 147 api_guard = Naming.api_guard_prefix + self.api_name(env) |
| 148 h_code.putln("#ifndef %s" % api_guard) |
| 149 h_code.putln("") |
| 150 self.generate_extern_c_macro_definition(h_code) |
| 151 if h_extension_types: |
| 152 h_code.putln("") |
| 153 for entry in h_extension_types: |
| 154 self.generate_cclass_header_code(entry.type, h_code) |
| 155 if i_code: |
| 156 self.generate_cclass_include_code(entry.type, i_code) |
| 157 if h_funcs: |
| 158 h_code.putln("") |
| 159 for entry in h_funcs: |
| 160 self.generate_public_declaration(entry, h_code, i_code) |
| 161 if h_vars: |
| 162 h_code.putln("") |
| 163 for entry in h_vars: |
| 164 self.generate_public_declaration(entry, h_code, i_code) |
| 165 h_code.putln("") |
| 166 h_code.putln("#endif /* !%s */" % api_guard) |
| 167 h_code.putln("") |
| 168 h_code.putln("#if PY_MAJOR_VERSION < 3") |
| 169 h_code.putln("PyMODINIT_FUNC init%s(void);" % env.module_name) |
| 170 h_code.putln("#else") |
| 171 h_code.putln("PyMODINIT_FUNC PyInit_%s(void);" % env.module_name) |
| 172 h_code.putln("#endif") |
| 173 h_code.putln("") |
| 174 h_code.putln("#endif /* !%s */" % h_guard) |
| 175 |
| 176 f = open_new_file(result.h_file) |
| 177 try: |
| 178 h_code.copyto(f) |
| 179 finally: |
| 180 f.close() |
| 181 |
| 182 def generate_public_declaration(self, entry, h_code, i_code): |
| 183 h_code.putln("%s %s;" % ( |
| 184 Naming.extern_c_macro, |
| 185 entry.type.declaration_code( |
| 186 entry.cname, dll_linkage = "DL_IMPORT"))) |
| 187 if i_code: |
| 188 i_code.putln("cdef extern %s" % |
| 189 entry.type.declaration_code(entry.cname, pyrex = 1)) |
| 190 |
| 191 def api_name(self, env): |
| 192 return env.qualified_name.replace(".", "__") |
| 193 |
| 194 def generate_api_code(self, env, result): |
| 195 def api_entries(entries, pxd=0): |
| 196 return [entry for entry in entries |
| 197 if entry.api or (pxd and entry.defined_in_pxd)] |
| 198 api_vars = api_entries(env.var_entries) |
| 199 api_funcs = api_entries(env.cfunc_entries) |
| 200 api_extension_types = api_entries(env.c_class_entries) |
| 201 if api_vars or api_funcs or api_extension_types: |
| 202 result.api_file = replace_suffix(result.c_file, "_api.h") |
| 203 h_code = Code.CCodeWriter() |
| 204 Code.GlobalState(h_code, self) |
| 205 api_guard = Naming.api_guard_prefix + self.api_name(env) |
| 206 h_code.put_h_guard(api_guard) |
| 207 h_code.putln('#include "Python.h"') |
| 208 if result.h_file: |
| 209 h_code.putln('#include "%s"' % os.path.basename(result.h_file)) |
| 210 if api_extension_types: |
| 211 h_code.putln("") |
| 212 for entry in api_extension_types: |
| 213 type = entry.type |
| 214 h_code.putln("static PyTypeObject *%s = 0;" % type.typeptr_c
name) |
| 215 h_code.putln("#define %s (*%s)" % ( |
| 216 type.typeobj_cname, type.typeptr_cname)) |
| 217 if api_funcs: |
| 218 h_code.putln("") |
| 219 for entry in api_funcs: |
| 220 type = CPtrType(entry.type) |
| 221 cname = env.mangle(Naming.func_prefix, entry.name) |
| 222 h_code.putln("static %s = 0;" % type.declaration_code(cname)
) |
| 223 h_code.putln("#define %s %s" % (entry.name, cname)) |
| 224 if api_vars: |
| 225 h_code.putln("") |
| 226 for entry in api_vars: |
| 227 type = CPtrType(entry.type) |
| 228 cname = env.mangle(Naming.varptr_prefix, entry.name) |
| 229 h_code.putln("static %s = 0;" % type.declaration_code(cname
)) |
| 230 h_code.putln("#define %s (*%s)" % (entry.name, cname)) |
| 231 h_code.put(UtilityCode.load_as_string("PyIdentifierFromString", "Imp
ortExport.c")[0]) |
| 232 h_code.put(UtilityCode.load_as_string("ModuleImport", "ImportExport.
c")[1]) |
| 233 if api_vars: |
| 234 h_code.put(UtilityCode.load_as_string("VoidPtrImport", "ImportEx
port.c")[1]) |
| 235 if api_funcs: |
| 236 h_code.put(UtilityCode.load_as_string("FunctionImport", "ImportE
xport.c")[1]) |
| 237 if api_extension_types: |
| 238 h_code.put(UtilityCode.load_as_string("TypeImport", "ImportExpor
t.c")[1]) |
| 239 h_code.putln("") |
| 240 h_code.putln("static int import_%s(void) {" % self.api_name(env)) |
| 241 h_code.putln("PyObject *module = 0;") |
| 242 h_code.putln('module = __Pyx_ImportModule("%s");' % env.qualified_na
me) |
| 243 h_code.putln("if (!module) goto bad;") |
| 244 for entry in api_funcs: |
| 245 cname = env.mangle(Naming.func_prefix, entry.name) |
| 246 sig = entry.type.signature_string() |
| 247 h_code.putln( |
| 248 'if (__Pyx_ImportFunction(module, "%s", (void (**)(void))&%s
, "%s") < 0) goto bad;' |
| 249 % (entry.name, cname, sig)) |
| 250 for entry in api_vars: |
| 251 cname = env.mangle(Naming.varptr_prefix, entry.name) |
| 252 sig = entry.type.declaration_code("") |
| 253 h_code.putln( |
| 254 'if (__Pyx_ImportVoidPtr(module, "%s", (void **)&%s, "%s") <
0) goto bad;' |
| 255 % (entry.name, cname, sig)) |
| 256 h_code.putln("Py_DECREF(module); module = 0;") |
| 257 for entry in api_extension_types: |
| 258 self.generate_type_import_call( |
| 259 entry.type, h_code, |
| 260 "if (!%s) goto bad;" % entry.type.typeptr_cname) |
| 261 h_code.putln("return 0;") |
| 262 h_code.putln("bad:") |
| 263 h_code.putln("Py_XDECREF(module);") |
| 264 h_code.putln("return -1;") |
| 265 h_code.putln("}") |
| 266 h_code.putln("") |
| 267 h_code.putln("#endif /* !%s */" % api_guard) |
| 268 |
| 269 f = open_new_file(result.api_file) |
| 270 try: |
| 271 h_code.copyto(f) |
| 272 finally: |
| 273 f.close() |
| 274 |
| 275 def generate_cclass_header_code(self, type, h_code): |
| 276 h_code.putln("%s %s %s;" % ( |
| 277 Naming.extern_c_macro, |
| 278 PyrexTypes.public_decl("PyTypeObject", "DL_IMPORT"), |
| 279 type.typeobj_cname)) |
| 280 |
| 281 def generate_cclass_include_code(self, type, i_code): |
| 282 i_code.putln("cdef extern class %s.%s:" % ( |
| 283 type.module_name, type.name)) |
| 284 i_code.indent() |
| 285 var_entries = type.scope.var_entries |
| 286 if var_entries: |
| 287 for entry in var_entries: |
| 288 i_code.putln("cdef %s" % |
| 289 entry.type.declaration_code(entry.cname, pyrex = 1)) |
| 290 else: |
| 291 i_code.putln("pass") |
| 292 i_code.dedent() |
| 293 |
| 294 def generate_c_code(self, env, options, result): |
| 295 modules = self.referenced_modules |
| 296 |
| 297 if Options.annotate or options.annotate: |
| 298 emit_linenums = False |
| 299 rootwriter = Annotate.AnnotationCCodeWriter() |
| 300 else: |
| 301 emit_linenums = options.emit_linenums |
| 302 rootwriter = Code.CCodeWriter(emit_linenums=emit_linenums, c_line_in
_traceback=options.c_line_in_traceback) |
| 303 globalstate = Code.GlobalState(rootwriter, self, emit_linenums, options.
common_utility_include_dir) |
| 304 globalstate.initialize_main_c_code() |
| 305 h_code = globalstate['h_code'] |
| 306 |
| 307 self.generate_module_preamble(env, modules, h_code) |
| 308 |
| 309 globalstate.module_pos = self.pos |
| 310 globalstate.directives = self.directives |
| 311 |
| 312 globalstate.use_utility_code(refnanny_utility_code) |
| 313 |
| 314 code = globalstate['before_global_var'] |
| 315 code.putln('#define __Pyx_MODULE_NAME "%s"' % self.full_module_name) |
| 316 code.putln("int %s%s = 0;" % (Naming.module_is_main, self.full_module_na
me.replace('.', '__'))) |
| 317 code.putln("") |
| 318 code.putln("/* Implementation of '%s' */" % env.qualified_name) |
| 319 |
| 320 code = globalstate['all_the_rest'] |
| 321 |
| 322 self.generate_cached_builtins_decls(env, code) |
| 323 self.generate_lambda_definitions(env, code) |
| 324 # generate normal variable and function definitions |
| 325 self.generate_variable_definitions(env, code) |
| 326 self.body.generate_function_definitions(env, code) |
| 327 code.mark_pos(None) |
| 328 self.generate_typeobj_definitions(env, code) |
| 329 self.generate_method_table(env, code) |
| 330 if env.has_import_star: |
| 331 self.generate_import_star(env, code) |
| 332 self.generate_pymoduledef_struct(env, code) |
| 333 |
| 334 # init_globals is inserted before this |
| 335 self.generate_module_init_func(modules[:-1], env, globalstate['init_modu
le']) |
| 336 self.generate_module_cleanup_func(env, globalstate['cleanup_module']) |
| 337 if Options.embed: |
| 338 self.generate_main_method(env, globalstate['main_method']) |
| 339 self.generate_filename_table(globalstate['filename_table']) |
| 340 |
| 341 self.generate_declarations_for_modules(env, modules, globalstate) |
| 342 h_code.write('\n') |
| 343 |
| 344 for utilcode in env.utility_code_list[:]: |
| 345 globalstate.use_utility_code(utilcode) |
| 346 globalstate.finalize_main_c_code() |
| 347 |
| 348 f = open_new_file(result.c_file) |
| 349 try: |
| 350 rootwriter.copyto(f) |
| 351 finally: |
| 352 f.close() |
| 353 result.c_file_generated = 1 |
| 354 if options.gdb_debug: |
| 355 self._serialize_lineno_map(env, rootwriter) |
| 356 if Options.annotate or options.annotate: |
| 357 self._generate_annotations(rootwriter, result) |
| 358 |
| 359 def _generate_annotations(self, rootwriter, result): |
| 360 self.annotate(rootwriter) |
| 361 rootwriter.save_annotation(result.main_source_file, result.c_file) |
| 362 |
| 363 # if we included files, additionally generate one annotation file for ea
ch |
| 364 if not self.scope.included_files: |
| 365 return |
| 366 |
| 367 search_include_file = self.scope.context.search_include_directories |
| 368 target_dir = os.path.abspath(os.path.dirname(result.c_file)) |
| 369 for included_file in self.scope.included_files: |
| 370 target_file = os.path.abspath(os.path.join(target_dir, included_file
)) |
| 371 target_file_dir = os.path.dirname(target_file) |
| 372 if not target_file_dir.startswith(target_dir): |
| 373 # any other directories may not be writable => avoid trying |
| 374 continue |
| 375 source_file = search_include_file(included_file, "", self.pos, inclu
de=True) |
| 376 if not source_file: |
| 377 continue |
| 378 if target_file_dir != target_dir and not os.path.exists(target_file_
dir): |
| 379 try: |
| 380 os.makedirs(target_file_dir) |
| 381 except OSError, e: |
| 382 import errno |
| 383 if e.errno != errno.EEXIST: |
| 384 raise |
| 385 rootwriter.save_annotation(source_file, target_file) |
| 386 |
| 387 def _serialize_lineno_map(self, env, ccodewriter): |
| 388 tb = env.context.gdb_debug_outputwriter |
| 389 markers = ccodewriter.buffer.allmarkers() |
| 390 |
| 391 d = {} |
| 392 for c_lineno, cython_lineno in enumerate(markers): |
| 393 if cython_lineno > 0: |
| 394 d.setdefault(cython_lineno, []).append(c_lineno + 1) |
| 395 |
| 396 tb.start('LineNumberMapping') |
| 397 for cython_lineno, c_linenos in sorted(d.iteritems()): |
| 398 attrs = { |
| 399 'c_linenos': ' '.join(map(str, c_linenos)), |
| 400 'cython_lineno': str(cython_lineno), |
| 401 } |
| 402 tb.start('LineNumber', attrs) |
| 403 tb.end('LineNumber') |
| 404 tb.end('LineNumberMapping') |
| 405 tb.serialize() |
| 406 |
| 407 def find_referenced_modules(self, env, module_list, modules_seen): |
| 408 if env not in modules_seen: |
| 409 modules_seen[env] = 1 |
| 410 for imported_module in env.cimported_modules: |
| 411 self.find_referenced_modules(imported_module, module_list, modul
es_seen) |
| 412 module_list.append(env) |
| 413 |
| 414 def sort_types_by_inheritance(self, type_dict, type_order, getkey): |
| 415 # copy the types into a list moving each parent type before |
| 416 # its first child |
| 417 type_list = [] |
| 418 for i, key in enumerate(type_order): |
| 419 new_entry = type_dict[key] |
| 420 |
| 421 # collect all base classes to check for children |
| 422 hierarchy = set() |
| 423 base = new_entry |
| 424 while base: |
| 425 base_type = base.type.base_type |
| 426 if not base_type: |
| 427 break |
| 428 base_key = getkey(base_type) |
| 429 hierarchy.add(base_key) |
| 430 base = type_dict.get(base_key) |
| 431 new_entry.base_keys = hierarchy |
| 432 |
| 433 # find the first (sub-)subclass and insert before that |
| 434 for j in range(i): |
| 435 entry = type_list[j] |
| 436 if key in entry.base_keys: |
| 437 type_list.insert(j, new_entry) |
| 438 break |
| 439 else: |
| 440 type_list.append(new_entry) |
| 441 return type_list |
| 442 |
| 443 def sort_type_hierarchy(self, module_list, env): |
| 444 # poor developer's OrderedDict |
| 445 vtab_dict, vtab_dict_order = {}, [] |
| 446 vtabslot_dict, vtabslot_dict_order = {}, [] |
| 447 |
| 448 for module in module_list: |
| 449 for entry in module.c_class_entries: |
| 450 if entry.used and not entry.in_cinclude: |
| 451 type = entry.type |
| 452 key = type.vtabstruct_cname |
| 453 if not key: |
| 454 continue |
| 455 if key in vtab_dict: |
| 456 # FIXME: this should *never* happen, but apparently it d
oes |
| 457 # for Cython generated utility code |
| 458 from Cython.Compiler.UtilityCode import NonManglingModul
eScope |
| 459 assert isinstance(entry.scope, NonManglingModuleScope),
str(entry.scope) |
| 460 assert isinstance(vtab_dict[key].scope, NonManglingModul
eScope), str(vtab_dict[key].scope) |
| 461 else: |
| 462 vtab_dict[key] = entry |
| 463 vtab_dict_order.append(key) |
| 464 all_defined_here = module is env |
| 465 for entry in module.type_entries: |
| 466 if entry.used and (all_defined_here or entry.defined_in_pxd): |
| 467 type = entry.type |
| 468 if type.is_extension_type and not entry.in_cinclude: |
| 469 type = entry.type |
| 470 key = type.objstruct_cname |
| 471 assert key not in vtabslot_dict, key |
| 472 vtabslot_dict[key] = entry |
| 473 vtabslot_dict_order.append(key) |
| 474 |
| 475 def vtabstruct_cname(entry_type): |
| 476 return entry_type.vtabstruct_cname |
| 477 vtab_list = self.sort_types_by_inheritance( |
| 478 vtab_dict, vtab_dict_order, vtabstruct_cname) |
| 479 |
| 480 def objstruct_cname(entry_type): |
| 481 return entry_type.objstruct_cname |
| 482 vtabslot_list = self.sort_types_by_inheritance( |
| 483 vtabslot_dict, vtabslot_dict_order, objstruct_cname) |
| 484 |
| 485 return (vtab_list, vtabslot_list) |
| 486 |
| 487 def sort_cdef_classes(self, env): |
| 488 key_func = operator.attrgetter('objstruct_cname') |
| 489 entry_dict, entry_order = {}, [] |
| 490 for entry in env.c_class_entries: |
| 491 key = key_func(entry.type) |
| 492 assert key not in entry_dict, key |
| 493 entry_dict[key] = entry |
| 494 entry_order.append(key) |
| 495 env.c_class_entries[:] = self.sort_types_by_inheritance( |
| 496 entry_dict, entry_order, key_func) |
| 497 |
| 498 def generate_type_definitions(self, env, modules, vtab_list, vtabslot_list,
code): |
| 499 # TODO: Why are these separated out? |
| 500 for entry in vtabslot_list: |
| 501 self.generate_objstruct_predeclaration(entry.type, code) |
| 502 vtabslot_entries = set(vtabslot_list) |
| 503 for module in modules: |
| 504 definition = module is env |
| 505 if definition: |
| 506 type_entries = module.type_entries |
| 507 else: |
| 508 type_entries = [] |
| 509 for entry in module.type_entries: |
| 510 if entry.defined_in_pxd: |
| 511 type_entries.append(entry) |
| 512 type_entries = [t for t in type_entries if t not in vtabslot_entries
] |
| 513 self.generate_type_header_code(type_entries, code) |
| 514 for entry in vtabslot_list: |
| 515 self.generate_objstruct_definition(entry.type, code) |
| 516 self.generate_typeobj_predeclaration(entry, code) |
| 517 for entry in vtab_list: |
| 518 self.generate_typeobj_predeclaration(entry, code) |
| 519 self.generate_exttype_vtable_struct(entry, code) |
| 520 self.generate_exttype_vtabptr_declaration(entry, code) |
| 521 self.generate_exttype_final_methods_declaration(entry, code) |
| 522 |
| 523 def generate_declarations_for_modules(self, env, modules, globalstate): |
| 524 typecode = globalstate['type_declarations'] |
| 525 typecode.putln("") |
| 526 typecode.putln("/*--- Type declarations ---*/") |
| 527 # This is to work around the fact that array.h isn't part of the C-API, |
| 528 # but we need to declare it earlier than utility code. |
| 529 if 'cpython.array' in [m.qualified_name for m in modules]: |
| 530 typecode.putln('#ifndef _ARRAYARRAY_H') |
| 531 typecode.putln('struct arrayobject;') |
| 532 typecode.putln('typedef struct arrayobject arrayobject;') |
| 533 typecode.putln('#endif') |
| 534 vtab_list, vtabslot_list = self.sort_type_hierarchy(modules, env) |
| 535 self.generate_type_definitions( |
| 536 env, modules, vtab_list, vtabslot_list, typecode) |
| 537 modulecode = globalstate['module_declarations'] |
| 538 for module in modules: |
| 539 defined_here = module is env |
| 540 modulecode.putln("") |
| 541 modulecode.putln("/* Module declarations from '%s' */" % module.qual
ified_name) |
| 542 self.generate_c_class_declarations(module, modulecode, defined_here) |
| 543 self.generate_cvariable_declarations(module, modulecode, defined_her
e) |
| 544 self.generate_cfunction_declarations(module, modulecode, defined_her
e) |
| 545 |
| 546 def generate_module_preamble(self, env, cimported_modules, code): |
| 547 code.putln("/* Generated by Cython %s */" % Version.watermark) |
| 548 code.putln("") |
| 549 code.putln("#define PY_SSIZE_T_CLEAN") |
| 550 |
| 551 # sizeof(PyLongObject.ob_digit[0]) may have been determined dynamically |
| 552 # at compile time in CPython, in which case we can't know the correct |
| 553 # storage size for an installed system. We can rely on it only if |
| 554 # pyconfig.h defines it statically, i.e. if it was set by "configure". |
| 555 # Once we include "Python.h", it will come up with its own idea about |
| 556 # a suitable value, which may or may not match the real one. |
| 557 code.putln("#ifndef CYTHON_USE_PYLONG_INTERNALS") |
| 558 code.putln("#ifdef PYLONG_BITS_IN_DIGIT") |
| 559 # assume it's an incorrect left-over |
| 560 code.putln("#define CYTHON_USE_PYLONG_INTERNALS 0") |
| 561 code.putln("#else") |
| 562 code.putln('#include "pyconfig.h"') |
| 563 code.putln("#ifdef PYLONG_BITS_IN_DIGIT") |
| 564 code.putln("#define CYTHON_USE_PYLONG_INTERNALS 1") |
| 565 code.putln("#else") |
| 566 code.putln("#define CYTHON_USE_PYLONG_INTERNALS 0") |
| 567 code.putln("#endif") |
| 568 code.putln("#endif") |
| 569 code.putln("#endif") |
| 570 |
| 571 for filename in env.python_include_files: |
| 572 code.putln('#include "%s"' % filename) |
| 573 code.putln("#ifndef Py_PYTHON_H") |
| 574 code.putln(" #error Python headers needed to compile C extensions, pl
ease install development version of Python.") |
| 575 code.putln("#elif PY_VERSION_HEX < 0x02040000") |
| 576 code.putln(" #error Cython requires Python 2.4+.") |
| 577 code.putln("#else") |
| 578 code.globalstate["end"].putln("#endif /* Py_PYTHON_H */") |
| 579 |
| 580 from Cython import __version__ |
| 581 code.putln('#define CYTHON_ABI "%s"' % __version__.replace('.', '_')) |
| 582 |
| 583 code.put(UtilityCode.load_as_string("CModulePreamble", "ModuleSetupCode.
c")[1]) |
| 584 |
| 585 code.put(""" |
| 586 #if PY_MAJOR_VERSION >= 3 |
| 587 #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) |
| 588 #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) |
| 589 #else |
| 590 """) |
| 591 if Future.division in env.context.future_directives: |
| 592 code.putln(" #define __Pyx_PyNumber_Divide(x,y) PyNumber_Tr
ueDivide(x,y)") |
| 593 code.putln(" #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_In
PlaceTrueDivide(x,y)") |
| 594 else: |
| 595 code.putln(" #define __Pyx_PyNumber_Divide(x,y) PyNumber_Di
vide(x,y)") |
| 596 code.putln(" #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_In
PlaceDivide(x,y)") |
| 597 code.putln("#endif") |
| 598 |
| 599 code.putln("") |
| 600 self.generate_extern_c_macro_definition(code) |
| 601 code.putln("") |
| 602 |
| 603 code.putln("#if defined(WIN32) || defined(MS_WINDOWS)") |
| 604 code.putln("#define _USE_MATH_DEFINES") |
| 605 code.putln("#endif") |
| 606 code.putln("#include <math.h>") |
| 607 |
| 608 code.putln("#define %s" % Naming.h_guard_prefix + self.api_name(env)) |
| 609 code.putln("#define %s" % Naming.api_guard_prefix + self.api_name(env)) |
| 610 self.generate_includes(env, cimported_modules, code) |
| 611 code.putln("") |
| 612 code.putln("#ifdef PYREX_WITHOUT_ASSERTIONS") |
| 613 code.putln("#define CYTHON_WITHOUT_ASSERTIONS") |
| 614 code.putln("#endif") |
| 615 code.putln("") |
| 616 |
| 617 if env.directives['ccomplex']: |
| 618 code.putln("") |
| 619 code.putln("#if !defined(CYTHON_CCOMPLEX)") |
| 620 code.putln("#define CYTHON_CCOMPLEX 1") |
| 621 code.putln("#endif") |
| 622 code.putln("") |
| 623 code.put(UtilityCode.load_as_string("UtilityFunctionPredeclarations", "M
oduleSetupCode.c")[0]) |
| 624 |
| 625 c_string_type = env.directives['c_string_type'] |
| 626 c_string_encoding = env.directives['c_string_encoding'] |
| 627 if c_string_type not in ('bytes', 'bytearray') and not c_string_encoding
: |
| 628 error(self.pos, "a default encoding must be provided if c_string_typ
e is not a byte type") |
| 629 code.putln('#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII %s' % int(c_s
tring_encoding == 'ascii')) |
| 630 if c_string_encoding == 'default': |
| 631 code.putln('#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 1') |
| 632 else: |
| 633 code.putln('#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 0') |
| 634 code.putln('#define __PYX_DEFAULT_STRING_ENCODING "%s"' % c_string_e
ncoding) |
| 635 if c_string_type == 'bytearray': |
| 636 c_string_func_name = 'ByteArray' |
| 637 else: |
| 638 c_string_func_name = c_string_type.title() |
| 639 code.putln('#define __Pyx_PyObject_FromString __Pyx_Py%s_FromString' % c
_string_func_name) |
| 640 code.putln('#define __Pyx_PyObject_FromStringAndSize __Pyx_Py%s_FromStri
ngAndSize' % c_string_func_name) |
| 641 code.put(UtilityCode.load_as_string("TypeConversions", "TypeConversion.c
")[0]) |
| 642 |
| 643 # These utility functions are assumed to exist and used elsewhere. |
| 644 PyrexTypes.c_long_type.create_to_py_utility_code(env) |
| 645 PyrexTypes.c_long_type.create_from_py_utility_code(env) |
| 646 PyrexTypes.c_int_type.create_from_py_utility_code(env) |
| 647 |
| 648 code.put(Nodes.branch_prediction_macros) |
| 649 code.putln('') |
| 650 code.putln('static PyObject *%s;' % env.module_cname) |
| 651 code.putln('static PyObject *%s;' % env.module_dict_cname) |
| 652 code.putln('static PyObject *%s;' % Naming.builtins_cname) |
| 653 code.putln('static PyObject *%s;' % Naming.empty_tuple) |
| 654 code.putln('static PyObject *%s;' % Naming.empty_bytes) |
| 655 if Options.pre_import is not None: |
| 656 code.putln('static PyObject *%s;' % Naming.preimport_cname) |
| 657 code.putln('static int %s;' % Naming.lineno_cname) |
| 658 code.putln('static int %s = 0;' % Naming.clineno_cname) |
| 659 code.putln('static const char * %s= %s;' % (Naming.cfilenm_cname, Naming
.file_c_macro)) |
| 660 code.putln('static const char *%s;' % Naming.filename_cname) |
| 661 |
| 662 def generate_extern_c_macro_definition(self, code): |
| 663 name = Naming.extern_c_macro |
| 664 code.putln("#ifndef %s" % name) |
| 665 code.putln(" #ifdef __cplusplus") |
| 666 code.putln(' #define %s extern "C"' % name) |
| 667 code.putln(" #else") |
| 668 code.putln(" #define %s extern" % name) |
| 669 code.putln(" #endif") |
| 670 code.putln("#endif") |
| 671 |
| 672 def generate_includes(self, env, cimported_modules, code): |
| 673 includes = [] |
| 674 for filename in env.include_files: |
| 675 byte_decoded_filenname = str(filename) |
| 676 if byte_decoded_filenname[0] == '<' and byte_decoded_filenname[-1] =
= '>': |
| 677 code.putln('#include %s' % byte_decoded_filenname) |
| 678 else: |
| 679 code.putln('#include "%s"' % byte_decoded_filenname) |
| 680 |
| 681 code.putln_openmp("#include <omp.h>") |
| 682 |
| 683 def generate_filename_table(self, code): |
| 684 code.putln("") |
| 685 code.putln("static const char *%s[] = {" % Naming.filetable_cname) |
| 686 if code.globalstate.filename_list: |
| 687 for source_desc in code.globalstate.filename_list: |
| 688 filename = os.path.basename(source_desc.get_filenametable_entry(
)) |
| 689 escaped_filename = filename.replace("\\", "\\\\").replace('"', r
'\"') |
| 690 code.putln('"%s",' % escaped_filename) |
| 691 else: |
| 692 # Some C compilers don't like an empty array |
| 693 code.putln("0") |
| 694 code.putln("};") |
| 695 |
| 696 def generate_type_predeclarations(self, env, code): |
| 697 pass |
| 698 |
| 699 def generate_type_header_code(self, type_entries, code): |
| 700 # Generate definitions of structs/unions/enums/typedefs/objstructs. |
| 701 #self.generate_gcc33_hack(env, code) # Is this still needed? |
| 702 # Forward declarations |
| 703 for entry in type_entries: |
| 704 if not entry.in_cinclude: |
| 705 #print "generate_type_header_code:", entry.name, repr(entry.type
) ### |
| 706 type = entry.type |
| 707 if type.is_typedef: # Must test this first! |
| 708 pass |
| 709 elif type.is_struct_or_union or type.is_cpp_class: |
| 710 self.generate_struct_union_predeclaration(entry, code) |
| 711 elif type.is_extension_type: |
| 712 self.generate_objstruct_predeclaration(type, code) |
| 713 # Actual declarations |
| 714 for entry in type_entries: |
| 715 if not entry.in_cinclude: |
| 716 #print "generate_type_header_code:", entry.name, repr(entry.type
) ### |
| 717 type = entry.type |
| 718 if type.is_typedef: # Must test this first! |
| 719 self.generate_typedef(entry, code) |
| 720 elif type.is_enum: |
| 721 self.generate_enum_definition(entry, code) |
| 722 elif type.is_struct_or_union: |
| 723 self.generate_struct_union_definition(entry, code) |
| 724 elif type.is_cpp_class: |
| 725 self.generate_cpp_class_definition(entry, code) |
| 726 elif type.is_extension_type: |
| 727 self.generate_objstruct_definition(type, code) |
| 728 |
| 729 def generate_gcc33_hack(self, env, code): |
| 730 # Workaround for spurious warning generation in gcc 3.3 |
| 731 code.putln("") |
| 732 for entry in env.c_class_entries: |
| 733 type = entry.type |
| 734 if not type.typedef_flag: |
| 735 name = type.objstruct_cname |
| 736 if name.startswith("__pyx_"): |
| 737 tail = name[6:] |
| 738 else: |
| 739 tail = name |
| 740 code.putln("typedef struct %s __pyx_gcc33_%s;" % ( |
| 741 name, tail)) |
| 742 |
| 743 def generate_typedef(self, entry, code): |
| 744 base_type = entry.type.typedef_base_type |
| 745 if base_type.is_numeric: |
| 746 try: |
| 747 writer = code.globalstate['numeric_typedefs'] |
| 748 except KeyError: |
| 749 writer = code |
| 750 else: |
| 751 writer = code |
| 752 writer.mark_pos(entry.pos) |
| 753 writer.putln("typedef %s;" % base_type.declaration_code(entry.cname)) |
| 754 |
| 755 def sue_predeclaration(self, type, kind, name): |
| 756 if type.typedef_flag: |
| 757 return "%s %s;\ntypedef %s %s %s;" % ( |
| 758 kind, name, |
| 759 kind, name, name) |
| 760 else: |
| 761 return "%s %s;" % (kind, name) |
| 762 |
| 763 def generate_struct_union_predeclaration(self, entry, code): |
| 764 type = entry.type |
| 765 if type.is_cpp_class and type.templates: |
| 766 code.putln("template <typename %s>" % ", typename ".join([T.declarat
ion_code("") for T in type.templates])) |
| 767 code.putln(self.sue_predeclaration(type, type.kind, type.cname)) |
| 768 |
| 769 def sue_header_footer(self, type, kind, name): |
| 770 header = "%s %s {" % (kind, name) |
| 771 footer = "};" |
| 772 return header, footer |
| 773 |
| 774 def generate_struct_union_definition(self, entry, code): |
| 775 code.mark_pos(entry.pos) |
| 776 type = entry.type |
| 777 scope = type.scope |
| 778 if scope: |
| 779 kind = type.kind |
| 780 packed = type.is_struct and type.packed |
| 781 if packed: |
| 782 kind = "%s %s" % (type.kind, "__Pyx_PACKED") |
| 783 code.globalstate.use_utility_code(packed_struct_utility_code) |
| 784 header, footer = \ |
| 785 self.sue_header_footer(type, kind, type.cname) |
| 786 if packed: |
| 787 code.putln("#if defined(__SUNPRO_C)") |
| 788 code.putln(" #pragma pack(1)") |
| 789 code.putln("#elif !defined(__GNUC__)") |
| 790 code.putln(" #pragma pack(push, 1)") |
| 791 code.putln("#endif") |
| 792 code.putln(header) |
| 793 var_entries = scope.var_entries |
| 794 if not var_entries: |
| 795 error(entry.pos, |
| 796 "Empty struct or union definition not allowed outside a" |
| 797 " 'cdef extern from' block") |
| 798 for attr in var_entries: |
| 799 code.putln( |
| 800 "%s;" % |
| 801 attr.type.declaration_code(attr.cname)) |
| 802 code.putln(footer) |
| 803 if packed: |
| 804 code.putln("#if defined(__SUNPRO_C)") |
| 805 code.putln(" #pragma pack()") |
| 806 code.putln("#elif !defined(__GNUC__)") |
| 807 code.putln(" #pragma pack(pop)") |
| 808 code.putln("#endif") |
| 809 |
| 810 def generate_cpp_class_definition(self, entry, code): |
| 811 code.mark_pos(entry.pos) |
| 812 type = entry.type |
| 813 scope = type.scope |
| 814 if scope: |
| 815 if type.templates: |
| 816 code.putln("template <class %s>" % ", class ".join([T.declaratio
n_code("") for T in type.templates])) |
| 817 # Just let everything be public. |
| 818 code.put("struct %s" % type.cname) |
| 819 if type.base_classes: |
| 820 base_class_decl = ", public ".join( |
| 821 [base_class.declaration_code("") for base_class in type.base
_classes]) |
| 822 code.put(" : public %s" % base_class_decl) |
| 823 code.putln(" {") |
| 824 has_virtual_methods = False |
| 825 has_destructor = False |
| 826 for attr in scope.var_entries: |
| 827 if attr.type.is_cfunction and attr.name != "<init>": |
| 828 code.put("virtual ") |
| 829 has_virtual_methods = True |
| 830 if attr.cname[0] == '~': |
| 831 has_destructor = True |
| 832 code.putln( |
| 833 "%s;" % |
| 834 attr.type.declaration_code(attr.cname)) |
| 835 if has_virtual_methods and not has_destructor: |
| 836 code.put("virtual ~%s() { }" % type.cname) |
| 837 code.putln("};") |
| 838 |
| 839 def generate_enum_definition(self, entry, code): |
| 840 code.mark_pos(entry.pos) |
| 841 type = entry.type |
| 842 name = entry.cname or entry.name or "" |
| 843 header, footer = \ |
| 844 self.sue_header_footer(type, "enum", name) |
| 845 code.putln(header) |
| 846 enum_values = entry.enum_values |
| 847 if not enum_values: |
| 848 error(entry.pos, |
| 849 "Empty enum definition not allowed outside a" |
| 850 " 'cdef extern from' block") |
| 851 else: |
| 852 last_entry = enum_values[-1] |
| 853 # this does not really generate code, just builds the result value |
| 854 for value_entry in enum_values: |
| 855 if value_entry.value_node is not None: |
| 856 value_entry.value_node.generate_evaluation_code(code) |
| 857 |
| 858 for value_entry in enum_values: |
| 859 if value_entry.value_node is None: |
| 860 value_code = value_entry.cname |
| 861 else: |
| 862 value_code = ("%s = %s" % ( |
| 863 value_entry.cname, |
| 864 value_entry.value_node.result())) |
| 865 if value_entry is not last_entry: |
| 866 value_code += "," |
| 867 code.putln(value_code) |
| 868 code.putln(footer) |
| 869 if entry.type.typedef_flag: |
| 870 # Not pre-declared. |
| 871 code.putln("typedef enum %s %s;" % (name, name)) |
| 872 |
| 873 def generate_typeobj_predeclaration(self, entry, code): |
| 874 code.putln("") |
| 875 name = entry.type.typeobj_cname |
| 876 if name: |
| 877 if entry.visibility == 'extern' and not entry.in_cinclude: |
| 878 code.putln("%s %s %s;" % ( |
| 879 Naming.extern_c_macro, |
| 880 PyrexTypes.public_decl("PyTypeObject", "DL_IMPORT"), |
| 881 name)) |
| 882 elif entry.visibility == 'public': |
| 883 code.putln("%s %s %s;" % ( |
| 884 Naming.extern_c_macro, |
| 885 PyrexTypes.public_decl("PyTypeObject", "DL_EXPORT"), |
| 886 name)) |
| 887 # ??? Do we really need the rest of this? ??? |
| 888 #else: |
| 889 # code.putln("static PyTypeObject %s;" % name) |
| 890 |
| 891 def generate_exttype_vtable_struct(self, entry, code): |
| 892 if not entry.used: |
| 893 return |
| 894 |
| 895 code.mark_pos(entry.pos) |
| 896 # Generate struct declaration for an extension type's vtable. |
| 897 type = entry.type |
| 898 scope = type.scope |
| 899 |
| 900 self.specialize_fused_types(scope) |
| 901 |
| 902 if type.vtabstruct_cname: |
| 903 code.putln("") |
| 904 code.putln( |
| 905 "struct %s {" % |
| 906 type.vtabstruct_cname) |
| 907 if type.base_type and type.base_type.vtabstruct_cname: |
| 908 code.putln("struct %s %s;" % ( |
| 909 type.base_type.vtabstruct_cname, |
| 910 Naming.obj_base_cname)) |
| 911 for method_entry in scope.cfunc_entries: |
| 912 if not method_entry.is_inherited: |
| 913 code.putln( |
| 914 "%s;" % method_entry.type.declaration_code("(*%s)" % met
hod_entry.cname)) |
| 915 code.putln( |
| 916 "};") |
| 917 |
| 918 def generate_exttype_vtabptr_declaration(self, entry, code): |
| 919 if not entry.used: |
| 920 return |
| 921 |
| 922 code.mark_pos(entry.pos) |
| 923 # Generate declaration of pointer to an extension type's vtable. |
| 924 type = entry.type |
| 925 if type.vtabptr_cname: |
| 926 code.putln("static struct %s *%s;" % ( |
| 927 type.vtabstruct_cname, |
| 928 type.vtabptr_cname)) |
| 929 |
| 930 def generate_exttype_final_methods_declaration(self, entry, code): |
| 931 if not entry.used: |
| 932 return |
| 933 |
| 934 code.mark_pos(entry.pos) |
| 935 # Generate final methods prototypes |
| 936 type = entry.type |
| 937 for method_entry in entry.type.scope.cfunc_entries: |
| 938 if not method_entry.is_inherited and method_entry.final_func_cname: |
| 939 declaration = method_entry.type.declaration_code( |
| 940 method_entry.final_func_cname) |
| 941 modifiers = code.build_function_modifiers(method_entry.func_modi
fiers) |
| 942 code.putln("static %s%s;" % (modifiers, declaration)) |
| 943 |
| 944 def generate_objstruct_predeclaration(self, type, code): |
| 945 if not type.scope: |
| 946 return |
| 947 code.putln(self.sue_predeclaration(type, "struct", type.objstruct_cname)
) |
| 948 |
| 949 def generate_objstruct_definition(self, type, code): |
| 950 code.mark_pos(type.pos) |
| 951 # Generate object struct definition for an |
| 952 # extension type. |
| 953 if not type.scope: |
| 954 return # Forward declared but never defined |
| 955 header, footer = \ |
| 956 self.sue_header_footer(type, "struct", type.objstruct_cname) |
| 957 code.putln(header) |
| 958 base_type = type.base_type |
| 959 if base_type: |
| 960 basestruct_cname = base_type.objstruct_cname |
| 961 if basestruct_cname == "PyTypeObject": |
| 962 # User-defined subclasses of type are heap allocated. |
| 963 basestruct_cname = "PyHeapTypeObject" |
| 964 code.putln( |
| 965 "%s%s %s;" % ( |
| 966 ("struct ", "")[base_type.typedef_flag], |
| 967 basestruct_cname, |
| 968 Naming.obj_base_cname)) |
| 969 else: |
| 970 code.putln( |
| 971 "PyObject_HEAD") |
| 972 if type.vtabslot_cname and not (type.base_type and type.base_type.vtabsl
ot_cname): |
| 973 code.putln( |
| 974 "struct %s *%s;" % ( |
| 975 type.vtabstruct_cname, |
| 976 type.vtabslot_cname)) |
| 977 for attr in type.scope.var_entries: |
| 978 if attr.is_declared_generic: |
| 979 attr_type = py_object_type |
| 980 else: |
| 981 attr_type = attr.type |
| 982 code.putln( |
| 983 "%s;" % |
| 984 attr_type.declaration_code(attr.cname)) |
| 985 code.putln(footer) |
| 986 if type.objtypedef_cname is not None: |
| 987 # Only for exposing public typedef name. |
| 988 code.putln("typedef struct %s %s;" % (type.objstruct_cname, type.obj
typedef_cname)) |
| 989 |
| 990 def generate_c_class_declarations(self, env, code, definition): |
| 991 for entry in env.c_class_entries: |
| 992 if definition or entry.defined_in_pxd: |
| 993 code.putln("static PyTypeObject *%s = 0;" % |
| 994 entry.type.typeptr_cname) |
| 995 |
| 996 def generate_cvariable_declarations(self, env, code, definition): |
| 997 if env.is_cython_builtin: |
| 998 return |
| 999 for entry in env.var_entries: |
| 1000 if (entry.in_cinclude or entry.in_closure or |
| 1001 (entry.visibility == 'private' and |
| 1002 not (entry.defined_in_pxd or entry.used))): |
| 1003 continue |
| 1004 |
| 1005 storage_class = None |
| 1006 dll_linkage = None |
| 1007 cname = None |
| 1008 init = None |
| 1009 |
| 1010 if entry.visibility == 'extern': |
| 1011 storage_class = Naming.extern_c_macro |
| 1012 dll_linkage = "DL_IMPORT" |
| 1013 elif entry.visibility == 'public': |
| 1014 storage_class = Naming.extern_c_macro |
| 1015 if definition: |
| 1016 dll_linkage = "DL_EXPORT" |
| 1017 else: |
| 1018 dll_linkage = "DL_IMPORT" |
| 1019 elif entry.visibility == 'private': |
| 1020 storage_class = "static" |
| 1021 dll_linkage = None |
| 1022 if entry.init is not None: |
| 1023 init = entry.type.literal_code(entry.init) |
| 1024 type = entry.type |
| 1025 cname = entry.cname |
| 1026 |
| 1027 if entry.defined_in_pxd and not definition: |
| 1028 storage_class = "static" |
| 1029 dll_linkage = None |
| 1030 type = CPtrType(type) |
| 1031 cname = env.mangle(Naming.varptr_prefix, entry.name) |
| 1032 init = 0 |
| 1033 |
| 1034 if storage_class: |
| 1035 code.put("%s " % storage_class) |
| 1036 code.put(type.declaration_code( |
| 1037 cname, dll_linkage = dll_linkage)) |
| 1038 if init is not None: |
| 1039 code.put_safe(" = %s" % init) |
| 1040 code.putln(";") |
| 1041 if entry.cname != cname: |
| 1042 code.putln("#define %s (*%s)" % (entry.cname, cname)) |
| 1043 |
| 1044 def generate_cfunction_declarations(self, env, code, definition): |
| 1045 for entry in env.cfunc_entries: |
| 1046 if entry.used or (entry.visibility == 'public' or entry.api): |
| 1047 generate_cfunction_declaration(entry, env, code, definition) |
| 1048 |
| 1049 def generate_variable_definitions(self, env, code): |
| 1050 for entry in env.var_entries: |
| 1051 if (not entry.in_cinclude and |
| 1052 entry.visibility == "public"): |
| 1053 code.put(entry.type.declaration_code(entry.cname)) |
| 1054 if entry.init is not None: |
| 1055 init = entry.type.literal_code(entry.init) |
| 1056 code.put_safe(" = %s" % init) |
| 1057 code.putln(";") |
| 1058 |
| 1059 def generate_typeobj_definitions(self, env, code): |
| 1060 full_module_name = env.qualified_name |
| 1061 for entry in env.c_class_entries: |
| 1062 #print "generate_typeobj_definitions:", entry.name |
| 1063 #print "...visibility =", entry.visibility |
| 1064 if entry.visibility != 'extern': |
| 1065 type = entry.type |
| 1066 scope = type.scope |
| 1067 if scope: # could be None if there was an error |
| 1068 self.generate_exttype_vtable(scope, code) |
| 1069 self.generate_new_function(scope, code, entry) |
| 1070 self.generate_dealloc_function(scope, code) |
| 1071 if scope.needs_gc(): |
| 1072 self.generate_traverse_function(scope, code, entry) |
| 1073 if scope.needs_tp_clear(): |
| 1074 self.generate_clear_function(scope, code, entry) |
| 1075 if scope.defines_any(["__getitem__"]): |
| 1076 self.generate_getitem_int_function(scope, code) |
| 1077 if scope.defines_any(["__setitem__", "__delitem__"]): |
| 1078 self.generate_ass_subscript_function(scope, code) |
| 1079 if scope.defines_any(["__getslice__", "__setslice__", "__del
slice__"]): |
| 1080 warning(self.pos, "__getslice__, __setslice__, and __del
slice__ are not supported by Python 3, use __getitem__, __setitem__, and __delit
em__ instead", 1) |
| 1081 code.putln("#if PY_MAJOR_VERSION >= 3") |
| 1082 code.putln("#error __getslice__, __setslice__, and __del
slice__ not supported in Python 3.") |
| 1083 code.putln("#endif") |
| 1084 if scope.defines_any(["__setslice__", "__delslice__"]): |
| 1085 self.generate_ass_slice_function(scope, code) |
| 1086 if scope.defines_any(["__getattr__","__getattribute__"]): |
| 1087 self.generate_getattro_function(scope, code) |
| 1088 if scope.defines_any(["__setattr__", "__delattr__"]): |
| 1089 self.generate_setattro_function(scope, code) |
| 1090 if scope.defines_any(["__get__"]): |
| 1091 self.generate_descr_get_function(scope, code) |
| 1092 if scope.defines_any(["__set__", "__delete__"]): |
| 1093 self.generate_descr_set_function(scope, code) |
| 1094 self.generate_property_accessors(scope, code) |
| 1095 self.generate_method_table(scope, code) |
| 1096 self.generate_getset_table(scope, code) |
| 1097 self.generate_typeobj_definition(full_module_name, entry, co
de) |
| 1098 |
| 1099 def generate_exttype_vtable(self, scope, code): |
| 1100 # Generate the definition of an extension type's vtable. |
| 1101 type = scope.parent_type |
| 1102 if type.vtable_cname: |
| 1103 code.putln("static struct %s %s;" % ( |
| 1104 type.vtabstruct_cname, |
| 1105 type.vtable_cname)) |
| 1106 |
| 1107 def generate_self_cast(self, scope, code): |
| 1108 type = scope.parent_type |
| 1109 code.putln( |
| 1110 "%s = (%s)o;" % ( |
| 1111 type.declaration_code("p"), |
| 1112 type.declaration_code(""))) |
| 1113 |
| 1114 def generate_new_function(self, scope, code, cclass_entry): |
| 1115 tp_slot = TypeSlots.ConstructorSlot("tp_new", '__new__') |
| 1116 slot_func = scope.mangle_internal("tp_new") |
| 1117 type = scope.parent_type |
| 1118 base_type = type.base_type |
| 1119 |
| 1120 have_entries, (py_attrs, py_buffers, memoryview_slices) = \ |
| 1121 scope.get_refcounted_entries() |
| 1122 is_final_type = scope.parent_type.is_final_type |
| 1123 if scope.is_internal: |
| 1124 # internal classes (should) never need None inits, normal zeroing wi
ll do |
| 1125 py_attrs = [] |
| 1126 cpp_class_attrs = [entry for entry in scope.var_entries |
| 1127 if entry.type.is_cpp_class] |
| 1128 |
| 1129 new_func_entry = scope.lookup_here("__new__") |
| 1130 if base_type or (new_func_entry and new_func_entry.is_special |
| 1131 and not new_func_entry.trivial_signature): |
| 1132 unused_marker = '' |
| 1133 else: |
| 1134 unused_marker = 'CYTHON_UNUSED ' |
| 1135 |
| 1136 if base_type: |
| 1137 freelist_size = 0 # not currently supported |
| 1138 else: |
| 1139 freelist_size = scope.directives.get('freelist', 0) |
| 1140 freelist_name = scope.mangle_internal(Naming.freelist_name) |
| 1141 freecount_name = scope.mangle_internal(Naming.freecount_name) |
| 1142 |
| 1143 decls = code.globalstate['decls'] |
| 1144 decls.putln("static PyObject *%s(PyTypeObject *t, PyObject *a, PyObject
*k); /*proto*/" % |
| 1145 slot_func) |
| 1146 code.putln("") |
| 1147 if freelist_size: |
| 1148 code.putln("static %s[%d];" % ( |
| 1149 scope.parent_type.declaration_code(freelist_name), |
| 1150 freelist_size)) |
| 1151 code.putln("static int %s = 0;" % freecount_name) |
| 1152 code.putln("") |
| 1153 code.putln( |
| 1154 "static PyObject *%s(PyTypeObject *t, %sPyObject *a, %sPyObject *k)
{" |
| 1155 % (slot_func, unused_marker, unused_marker)) |
| 1156 |
| 1157 need_self_cast = (type.vtabslot_cname or |
| 1158 (py_buffers or memoryview_slices or py_attrs) or |
| 1159 cpp_class_attrs) |
| 1160 if need_self_cast: |
| 1161 code.putln("%s;" % scope.parent_type.declaration_code("p")) |
| 1162 if base_type: |
| 1163 tp_new = TypeSlots.get_base_slot_function(scope, tp_slot) |
| 1164 if tp_new is None: |
| 1165 tp_new = "%s->tp_new" % base_type.typeptr_cname |
| 1166 code.putln("PyObject *o = %s(t, a, k);" % tp_new) |
| 1167 else: |
| 1168 code.putln("PyObject *o;") |
| 1169 if freelist_size: |
| 1170 code.globalstate.use_utility_code( |
| 1171 UtilityCode.load_cached("IncludeStringH", "StringTools.c")) |
| 1172 if is_final_type: |
| 1173 type_safety_check = '' |
| 1174 else: |
| 1175 type_safety_check = ' & ((t->tp_flags & (Py_TPFLAGS_IS_ABSTR
ACT | Py_TPFLAGS_HEAPTYPE)) == 0)' |
| 1176 obj_struct = type.declaration_code("", deref=True) |
| 1177 code.putln("if (CYTHON_COMPILING_IN_CPYTHON && likely((%s > 0) &
(t->tp_basicsize == sizeof(%s))%s)) {" % ( |
| 1178 freecount_name, obj_struct, type_safety_check)) |
| 1179 code.putln("o = (PyObject*)%s[--%s];" % ( |
| 1180 freelist_name, freecount_name)) |
| 1181 code.putln("memset(o, 0, sizeof(%s));" % obj_struct) |
| 1182 code.putln("(void) PyObject_INIT(o, t);") |
| 1183 if scope.needs_gc(): |
| 1184 code.putln("PyObject_GC_Track(o);") |
| 1185 code.putln("} else {") |
| 1186 if not is_final_type: |
| 1187 code.putln("if (likely((t->tp_flags & Py_TPFLAGS_IS_ABSTRACT) ==
0)) {") |
| 1188 code.putln("o = (*t->tp_alloc)(t, 0);") |
| 1189 if not is_final_type: |
| 1190 code.putln("} else {") |
| 1191 code.putln("o = (PyObject *) PyBaseObject_Type.tp_new(t, %s, 0);
" % Naming.empty_tuple) |
| 1192 code.putln("}") |
| 1193 code.putln("if (unlikely(!o)) return 0;") |
| 1194 if freelist_size and not base_type: |
| 1195 code.putln('}') |
| 1196 if need_self_cast: |
| 1197 code.putln("p = %s;" % type.cast_code("o")) |
| 1198 #if need_self_cast: |
| 1199 # self.generate_self_cast(scope, code) |
| 1200 if type.vtabslot_cname: |
| 1201 vtab_base_type = type |
| 1202 while vtab_base_type.base_type and vtab_base_type.base_type.vtabstru
ct_cname: |
| 1203 vtab_base_type = vtab_base_type.base_type |
| 1204 if vtab_base_type is not type: |
| 1205 struct_type_cast = "(struct %s*)" % vtab_base_type.vtabstruct_cn
ame |
| 1206 else: |
| 1207 struct_type_cast = "" |
| 1208 code.putln("p->%s = %s%s;" % ( |
| 1209 type.vtabslot_cname, |
| 1210 struct_type_cast, type.vtabptr_cname)) |
| 1211 |
| 1212 for entry in cpp_class_attrs: |
| 1213 code.putln("new((void*)&(p->%s)) %s();" % |
| 1214 (entry.cname, entry.type.declaration_code(""))) |
| 1215 |
| 1216 for entry in py_attrs: |
| 1217 code.put_init_var_to_py_none(entry, "p->%s", nanny=False) |
| 1218 |
| 1219 for entry in memoryview_slices: |
| 1220 code.putln("p->%s.data = NULL;" % entry.cname) |
| 1221 code.putln("p->%s.memview = NULL;" % entry.cname) |
| 1222 |
| 1223 for entry in py_buffers: |
| 1224 code.putln("p->%s.obj = NULL;" % entry.cname) |
| 1225 |
| 1226 if cclass_entry.cname == '__pyx_memoryviewslice': |
| 1227 code.putln("p->from_slice.memview = NULL;") |
| 1228 |
| 1229 if new_func_entry and new_func_entry.is_special: |
| 1230 if new_func_entry.trivial_signature: |
| 1231 cinit_args = "o, %s, NULL" % Naming.empty_tuple |
| 1232 else: |
| 1233 cinit_args = "o, a, k" |
| 1234 code.putln( |
| 1235 "if (unlikely(%s(%s) < 0)) {" % |
| 1236 (new_func_entry.func_cname, cinit_args)) |
| 1237 code.put_decref_clear("o", py_object_type, nanny=False) |
| 1238 code.putln( |
| 1239 "}") |
| 1240 code.putln( |
| 1241 "return o;") |
| 1242 code.putln( |
| 1243 "}") |
| 1244 |
| 1245 def generate_dealloc_function(self, scope, code): |
| 1246 tp_slot = TypeSlots.ConstructorSlot("tp_dealloc", '__dealloc__') |
| 1247 slot_func = scope.mangle_internal("tp_dealloc") |
| 1248 base_type = scope.parent_type.base_type |
| 1249 if tp_slot.slot_code(scope) != slot_func: |
| 1250 return # never used |
| 1251 |
| 1252 slot_func_cname = scope.mangle_internal("tp_dealloc") |
| 1253 code.putln("") |
| 1254 code.putln( |
| 1255 "static void %s(PyObject *o) {" % slot_func_cname) |
| 1256 |
| 1257 is_final_type = scope.parent_type.is_final_type |
| 1258 needs_gc = scope.needs_gc() |
| 1259 |
| 1260 weakref_slot = scope.lookup_here("__weakref__") |
| 1261 if weakref_slot not in scope.var_entries: |
| 1262 weakref_slot = None |
| 1263 |
| 1264 _, (py_attrs, _, memoryview_slices) = scope.get_refcounted_entries() |
| 1265 cpp_class_attrs = [entry for entry in scope.var_entries |
| 1266 if entry.type.is_cpp_class] |
| 1267 |
| 1268 if py_attrs or cpp_class_attrs or memoryview_slices or weakref_slot: |
| 1269 self.generate_self_cast(scope, code) |
| 1270 |
| 1271 if not is_final_type: |
| 1272 # in Py3.4+, call tp_finalize() as early as possible |
| 1273 code.putln("#if PY_VERSION_HEX >= 0x030400a1") |
| 1274 if needs_gc: |
| 1275 finalised_check = '!_PyGC_FINALIZED(o)' |
| 1276 else: |
| 1277 finalised_check = ( |
| 1278 '(!PyType_IS_GC(Py_TYPE(o)) || !_PyGC_FINALIZED(o))') |
| 1279 code.putln("if (unlikely(Py_TYPE(o)->tp_finalize) && %s) {" % |
| 1280 finalised_check) |
| 1281 # if instance was resurrected by finaliser, return |
| 1282 code.putln("if (PyObject_CallFinalizerFromDealloc(o)) return;") |
| 1283 code.putln("}") |
| 1284 code.putln("#endif") |
| 1285 |
| 1286 if needs_gc: |
| 1287 # We must mark this object as (gc) untracked while tearing |
| 1288 # it down, lest the garbage collection is invoked while |
| 1289 # running this destructor. |
| 1290 code.putln("PyObject_GC_UnTrack(o);") |
| 1291 |
| 1292 # call the user's __dealloc__ |
| 1293 self.generate_usr_dealloc_call(scope, code) |
| 1294 |
| 1295 if weakref_slot: |
| 1296 code.putln("if (p->__weakref__) PyObject_ClearWeakRefs(o);") |
| 1297 |
| 1298 for entry in cpp_class_attrs: |
| 1299 code.putln("__Pyx_call_destructor(&p->%s);" % entry.cname) |
| 1300 |
| 1301 for entry in py_attrs: |
| 1302 code.put_xdecref_clear("p->%s" % entry.cname, entry.type, nanny=Fals
e, |
| 1303 clear_before_decref=True) |
| 1304 |
| 1305 for entry in memoryview_slices: |
| 1306 code.put_xdecref_memoryviewslice("p->%s" % entry.cname, |
| 1307 have_gil=True) |
| 1308 |
| 1309 if base_type: |
| 1310 if needs_gc: |
| 1311 # The base class deallocator probably expects this to be tracked
, |
| 1312 # so undo the untracking above. |
| 1313 if base_type.scope and base_type.scope.needs_gc(): |
| 1314 code.putln("PyObject_GC_Track(o);") |
| 1315 else: |
| 1316 code.putln("#if CYTHON_COMPILING_IN_CPYTHON") |
| 1317 code.putln("if (PyType_IS_GC(Py_TYPE(o)->tp_base))") |
| 1318 code.putln("#endif") |
| 1319 code.putln("PyObject_GC_Track(o);") |
| 1320 |
| 1321 tp_dealloc = TypeSlots.get_base_slot_function(scope, tp_slot) |
| 1322 if tp_dealloc is not None: |
| 1323 code.putln("%s(o);" % tp_dealloc) |
| 1324 elif base_type.is_builtin_type: |
| 1325 code.putln("%s->tp_dealloc(o);" % base_type.typeptr_cname) |
| 1326 else: |
| 1327 # This is an externally defined type. Calling through the |
| 1328 # cimported base type pointer directly interacts badly with |
| 1329 # the module cleanup, which may already have cleared it. |
| 1330 # In that case, fall back to traversing the type hierarchy. |
| 1331 base_cname = base_type.typeptr_cname |
| 1332 code.putln("if (likely(%s)) %s->tp_dealloc(o); " |
| 1333 "else __Pyx_call_next_tp_dealloc(o, %s);" % ( |
| 1334 base_cname, base_cname, slot_func_cname)) |
| 1335 code.globalstate.use_utility_code( |
| 1336 UtilityCode.load_cached("CallNextTpDealloc", "ExtensionTypes
.c")) |
| 1337 else: |
| 1338 freelist_size = scope.directives.get('freelist', 0) |
| 1339 if freelist_size: |
| 1340 freelist_name = scope.mangle_internal(Naming.freelist_name) |
| 1341 freecount_name = scope.mangle_internal(Naming.freecount_name) |
| 1342 |
| 1343 if is_final_type: |
| 1344 type_safety_check = '' |
| 1345 else: |
| 1346 type_safety_check = ( |
| 1347 ' & ((Py_TYPE(o)->tp_flags & (Py_TPFLAGS_IS_ABSTRACT | P
y_TPFLAGS_HEAPTYPE)) == 0)') |
| 1348 |
| 1349 type = scope.parent_type |
| 1350 code.putln("if (CYTHON_COMPILING_IN_CPYTHON && ((%s < %d) & (Py_
TYPE(o)->tp_basicsize == sizeof(%s))%s)) {" % ( |
| 1351 freecount_name, freelist_size, type.declaration_code("", der
ef=True), |
| 1352 type_safety_check)) |
| 1353 code.putln("%s[%s++] = %s;" % ( |
| 1354 freelist_name, freecount_name, type.cast_code("o"))) |
| 1355 code.putln("} else {") |
| 1356 code.putln("(*Py_TYPE(o)->tp_free)(o);") |
| 1357 if freelist_size: |
| 1358 code.putln("}") |
| 1359 code.putln( |
| 1360 "}") |
| 1361 |
| 1362 def generate_usr_dealloc_call(self, scope, code): |
| 1363 entry = scope.lookup_here("__dealloc__") |
| 1364 if not entry: |
| 1365 return |
| 1366 |
| 1367 code.putln("{") |
| 1368 code.putln("PyObject *etype, *eval, *etb;") |
| 1369 code.putln("PyErr_Fetch(&etype, &eval, &etb);") |
| 1370 code.putln("++Py_REFCNT(o);") |
| 1371 code.putln("%s(o);" % entry.func_cname) |
| 1372 code.putln("--Py_REFCNT(o);") |
| 1373 code.putln("PyErr_Restore(etype, eval, etb);") |
| 1374 code.putln("}") |
| 1375 |
| 1376 def generate_traverse_function(self, scope, code, cclass_entry): |
| 1377 tp_slot = TypeSlots.GCDependentSlot("tp_traverse") |
| 1378 slot_func = scope.mangle_internal("tp_traverse") |
| 1379 base_type = scope.parent_type.base_type |
| 1380 if tp_slot.slot_code(scope) != slot_func: |
| 1381 return # never used |
| 1382 code.putln("") |
| 1383 code.putln( |
| 1384 "static int %s(PyObject *o, visitproc v, void *a) {" |
| 1385 % slot_func) |
| 1386 |
| 1387 have_entries, (py_attrs, py_buffers, memoryview_slices) = ( |
| 1388 scope.get_refcounted_entries(include_gc_simple=False)) |
| 1389 |
| 1390 if base_type or py_attrs: |
| 1391 code.putln("int e;") |
| 1392 |
| 1393 if py_attrs or py_buffers: |
| 1394 self.generate_self_cast(scope, code) |
| 1395 |
| 1396 if base_type: |
| 1397 # want to call it explicitly if possible so inlining can be performe
d |
| 1398 static_call = TypeSlots.get_base_slot_function(scope, tp_slot) |
| 1399 if static_call: |
| 1400 code.putln("e = %s(o, v, a); if (e) return e;" % static_call) |
| 1401 elif base_type.is_builtin_type: |
| 1402 base_cname = base_type.typeptr_cname |
| 1403 code.putln("if (!%s->tp_traverse); else { e = %s->tp_traverse(o,
v,a); if (e) return e; }" % ( |
| 1404 base_cname, base_cname)) |
| 1405 else: |
| 1406 # This is an externally defined type. Calling through the |
| 1407 # cimported base type pointer directly interacts badly with |
| 1408 # the module cleanup, which may already have cleared it. |
| 1409 # In that case, fall back to traversing the type hierarchy. |
| 1410 base_cname = base_type.typeptr_cname |
| 1411 code.putln("e = ((likely(%s)) ? ((%s->tp_traverse) ? %s->tp_trav
erse(o, v, a) : 0) : __Pyx_call_next_tp_traverse(o, v, a, %s)); if (e) return e;
" % ( |
| 1412 base_cname, base_cname, base_cname, slot_func)) |
| 1413 code.globalstate.use_utility_code( |
| 1414 UtilityCode.load_cached("CallNextTpTraverse", "ExtensionType
s.c")) |
| 1415 |
| 1416 for entry in py_attrs: |
| 1417 var_code = "p->%s" % entry.cname |
| 1418 code.putln( |
| 1419 "if (%s) {" |
| 1420 % var_code) |
| 1421 if entry.type.is_extension_type: |
| 1422 var_code = "((PyObject*)%s)" % var_code |
| 1423 code.putln( |
| 1424 "e = (*v)(%s, a); if (e) return e;" |
| 1425 % var_code) |
| 1426 code.putln( |
| 1427 "}") |
| 1428 |
| 1429 # Traverse buffer exporting objects. |
| 1430 # Note: not traversing memoryview attributes of memoryview slices! |
| 1431 # When triggered by the GC, it would cause multiple visits (gc_refs |
| 1432 # subtractions which is not matched by its reference count!) |
| 1433 for entry in py_buffers: |
| 1434 cname = entry.cname + ".obj" |
| 1435 code.putln("if (p->%s) {" % cname) |
| 1436 code.putln( "e = (*v)(p->%s, a); if (e) return e;" % cname) |
| 1437 code.putln("}") |
| 1438 |
| 1439 code.putln( |
| 1440 "return 0;") |
| 1441 code.putln( |
| 1442 "}") |
| 1443 |
| 1444 def generate_clear_function(self, scope, code, cclass_entry): |
| 1445 tp_slot = TypeSlots.GCDependentSlot("tp_clear") |
| 1446 slot_func = scope.mangle_internal("tp_clear") |
| 1447 base_type = scope.parent_type.base_type |
| 1448 if tp_slot.slot_code(scope) != slot_func: |
| 1449 return # never used |
| 1450 |
| 1451 have_entries, (py_attrs, py_buffers, memoryview_slices) = ( |
| 1452 scope.get_refcounted_entries(include_gc_simple=False)) |
| 1453 |
| 1454 if py_attrs or py_buffers or base_type: |
| 1455 unused = '' |
| 1456 else: |
| 1457 unused = 'CYTHON_UNUSED ' |
| 1458 |
| 1459 code.putln("") |
| 1460 code.putln("static int %s(%sPyObject *o) {" % (slot_func, unused)) |
| 1461 |
| 1462 if py_attrs and Options.clear_to_none: |
| 1463 code.putln("PyObject* tmp;") |
| 1464 |
| 1465 if py_attrs or py_buffers: |
| 1466 self.generate_self_cast(scope, code) |
| 1467 |
| 1468 if base_type: |
| 1469 # want to call it explicitly if possible so inlining can be performe
d |
| 1470 static_call = TypeSlots.get_base_slot_function(scope, tp_slot) |
| 1471 if static_call: |
| 1472 code.putln("%s(o);" % static_call) |
| 1473 elif base_type.is_builtin_type: |
| 1474 base_cname = base_type.typeptr_cname |
| 1475 code.putln("if (!%s->tp_clear); else %s->tp_clear(o);" % ( |
| 1476 base_cname, base_cname)) |
| 1477 else: |
| 1478 # This is an externally defined type. Calling through the |
| 1479 # cimported base type pointer directly interacts badly with |
| 1480 # the module cleanup, which may already have cleared it. |
| 1481 # In that case, fall back to traversing the type hierarchy. |
| 1482 base_cname = base_type.typeptr_cname |
| 1483 code.putln("if (likely(%s)) { if (%s->tp_clear) %s->tp_clear(o);
} else __Pyx_call_next_tp_clear(o, %s);" % ( |
| 1484 base_cname, base_cname, base_cname, slot_func)) |
| 1485 code.globalstate.use_utility_code( |
| 1486 UtilityCode.load_cached("CallNextTpClear", "ExtensionTypes.c
")) |
| 1487 |
| 1488 if Options.clear_to_none: |
| 1489 for entry in py_attrs: |
| 1490 name = "p->%s" % entry.cname |
| 1491 code.putln("tmp = ((PyObject*)%s);" % name) |
| 1492 if entry.is_declared_generic: |
| 1493 code.put_init_to_py_none(name, py_object_type, nanny=False) |
| 1494 else: |
| 1495 code.put_init_to_py_none(name, entry.type, nanny=False) |
| 1496 code.putln("Py_XDECREF(tmp);") |
| 1497 else: |
| 1498 for entry in py_attrs: |
| 1499 code.putln("Py_CLEAR(p->%s);" % entry.cname) |
| 1500 |
| 1501 for entry in py_buffers: |
| 1502 # Note: shouldn't this call __Pyx_ReleaseBuffer ?? |
| 1503 code.putln("Py_CLEAR(p->%s.obj);" % entry.cname) |
| 1504 |
| 1505 if cclass_entry.cname == '__pyx_memoryviewslice': |
| 1506 code.putln("__PYX_XDEC_MEMVIEW(&p->from_slice, 1);") |
| 1507 |
| 1508 code.putln( |
| 1509 "return 0;") |
| 1510 code.putln( |
| 1511 "}") |
| 1512 |
| 1513 def generate_getitem_int_function(self, scope, code): |
| 1514 # This function is put into the sq_item slot when |
| 1515 # a __getitem__ method is present. It converts its |
| 1516 # argument to a Python integer and calls mp_subscript. |
| 1517 code.putln( |
| 1518 "static PyObject *%s(PyObject *o, Py_ssize_t i) {" % |
| 1519 scope.mangle_internal("sq_item")) |
| 1520 code.putln( |
| 1521 "PyObject *r;") |
| 1522 code.putln( |
| 1523 "PyObject *x = PyInt_FromSsize_t(i); if(!x) return 0;") |
| 1524 code.putln( |
| 1525 "r = Py_TYPE(o)->tp_as_mapping->mp_subscript(o, x);") |
| 1526 code.putln( |
| 1527 "Py_DECREF(x);") |
| 1528 code.putln( |
| 1529 "return r;") |
| 1530 code.putln( |
| 1531 "}") |
| 1532 |
| 1533 def generate_ass_subscript_function(self, scope, code): |
| 1534 # Setting and deleting an item are both done through |
| 1535 # the ass_subscript method, so we dispatch to user's __setitem__ |
| 1536 # or __delitem__, or raise an exception. |
| 1537 base_type = scope.parent_type.base_type |
| 1538 set_entry = scope.lookup_here("__setitem__") |
| 1539 del_entry = scope.lookup_here("__delitem__") |
| 1540 code.putln("") |
| 1541 code.putln( |
| 1542 "static int %s(PyObject *o, PyObject *i, PyObject *v) {" % |
| 1543 scope.mangle_internal("mp_ass_subscript")) |
| 1544 code.putln( |
| 1545 "if (v) {") |
| 1546 if set_entry: |
| 1547 code.putln( |
| 1548 "return %s(o, i, v);" % |
| 1549 set_entry.func_cname) |
| 1550 else: |
| 1551 self.generate_guarded_basetype_call( |
| 1552 base_type, "tp_as_mapping", "mp_ass_subscript", "o, i, v", code) |
| 1553 code.putln( |
| 1554 "PyErr_Format(PyExc_NotImplementedError,") |
| 1555 code.putln( |
| 1556 ' "Subscript assignment not supported by %.200s", Py_TYPE(o
)->tp_name);') |
| 1557 code.putln( |
| 1558 "return -1;") |
| 1559 code.putln( |
| 1560 "}") |
| 1561 code.putln( |
| 1562 "else {") |
| 1563 if del_entry: |
| 1564 code.putln( |
| 1565 "return %s(o, i);" % |
| 1566 del_entry.func_cname) |
| 1567 else: |
| 1568 self.generate_guarded_basetype_call( |
| 1569 base_type, "tp_as_mapping", "mp_ass_subscript", "o, i, v", code) |
| 1570 code.putln( |
| 1571 "PyErr_Format(PyExc_NotImplementedError,") |
| 1572 code.putln( |
| 1573 ' "Subscript deletion not supported by %.200s", Py_TYPE(o)-
>tp_name);') |
| 1574 code.putln( |
| 1575 "return -1;") |
| 1576 code.putln( |
| 1577 "}") |
| 1578 code.putln( |
| 1579 "}") |
| 1580 |
| 1581 def generate_guarded_basetype_call( |
| 1582 self, base_type, substructure, slot, args, code): |
| 1583 if base_type: |
| 1584 base_tpname = base_type.typeptr_cname |
| 1585 if substructure: |
| 1586 code.putln( |
| 1587 "if (%s->%s && %s->%s->%s)" % ( |
| 1588 base_tpname, substructure, base_tpname, substructure, sl
ot)) |
| 1589 code.putln( |
| 1590 " return %s->%s->%s(%s);" % ( |
| 1591 base_tpname, substructure, slot, args)) |
| 1592 else: |
| 1593 code.putln( |
| 1594 "if (%s->%s)" % ( |
| 1595 base_tpname, slot)) |
| 1596 code.putln( |
| 1597 " return %s->%s(%s);" % ( |
| 1598 base_tpname, slot, args)) |
| 1599 |
| 1600 def generate_ass_slice_function(self, scope, code): |
| 1601 # Setting and deleting a slice are both done through |
| 1602 # the ass_slice method, so we dispatch to user's __setslice__ |
| 1603 # or __delslice__, or raise an exception. |
| 1604 base_type = scope.parent_type.base_type |
| 1605 set_entry = scope.lookup_here("__setslice__") |
| 1606 del_entry = scope.lookup_here("__delslice__") |
| 1607 code.putln("") |
| 1608 code.putln( |
| 1609 "static int %s(PyObject *o, Py_ssize_t i, Py_ssize_t j, PyObject *v)
{" % |
| 1610 scope.mangle_internal("sq_ass_slice")) |
| 1611 code.putln( |
| 1612 "if (v) {") |
| 1613 if set_entry: |
| 1614 code.putln( |
| 1615 "return %s(o, i, j, v);" % |
| 1616 set_entry.func_cname) |
| 1617 else: |
| 1618 self.generate_guarded_basetype_call( |
| 1619 base_type, "tp_as_sequence", "sq_ass_slice", "o, i, j, v", code) |
| 1620 code.putln( |
| 1621 "PyErr_Format(PyExc_NotImplementedError,") |
| 1622 code.putln( |
| 1623 ' "2-element slice assignment not supported by %.200s", Py_
TYPE(o)->tp_name);') |
| 1624 code.putln( |
| 1625 "return -1;") |
| 1626 code.putln( |
| 1627 "}") |
| 1628 code.putln( |
| 1629 "else {") |
| 1630 if del_entry: |
| 1631 code.putln( |
| 1632 "return %s(o, i, j);" % |
| 1633 del_entry.func_cname) |
| 1634 else: |
| 1635 self.generate_guarded_basetype_call( |
| 1636 base_type, "tp_as_sequence", "sq_ass_slice", "o, i, j, v", code) |
| 1637 code.putln( |
| 1638 "PyErr_Format(PyExc_NotImplementedError,") |
| 1639 code.putln( |
| 1640 ' "2-element slice deletion not supported by %.200s", Py_TY
PE(o)->tp_name);') |
| 1641 code.putln( |
| 1642 "return -1;") |
| 1643 code.putln( |
| 1644 "}") |
| 1645 code.putln( |
| 1646 "}") |
| 1647 |
| 1648 def generate_getattro_function(self, scope, code): |
| 1649 # First try to get the attribute using __getattribute__, if defined, or |
| 1650 # PyObject_GenericGetAttr. |
| 1651 # |
| 1652 # If that raises an AttributeError, call the __getattr__ if defined. |
| 1653 # |
| 1654 # In both cases, defined can be in this class, or any base class. |
| 1655 def lookup_here_or_base(n,type=None): |
| 1656 # Recursive lookup |
| 1657 if type is None: |
| 1658 type = scope.parent_type |
| 1659 r = type.scope.lookup_here(n) |
| 1660 if r is None and \ |
| 1661 type.base_type is not None: |
| 1662 return lookup_here_or_base(n,type.base_type) |
| 1663 else: |
| 1664 return r |
| 1665 getattr_entry = lookup_here_or_base("__getattr__") |
| 1666 getattribute_entry = lookup_here_or_base("__getattribute__") |
| 1667 code.putln("") |
| 1668 code.putln( |
| 1669 "static PyObject *%s(PyObject *o, PyObject *n) {" |
| 1670 % scope.mangle_internal("tp_getattro")) |
| 1671 if getattribute_entry is not None: |
| 1672 code.putln( |
| 1673 "PyObject *v = %s(o, n);" % |
| 1674 getattribute_entry.func_cname) |
| 1675 else: |
| 1676 code.putln( |
| 1677 "PyObject *v = PyObject_GenericGetAttr(o, n);") |
| 1678 if getattr_entry is not None: |
| 1679 code.putln( |
| 1680 "if (!v && PyErr_ExceptionMatches(PyExc_AttributeError)) {") |
| 1681 code.putln( |
| 1682 "PyErr_Clear();") |
| 1683 code.putln( |
| 1684 "v = %s(o, n);" % |
| 1685 getattr_entry.func_cname) |
| 1686 code.putln( |
| 1687 "}") |
| 1688 code.putln( |
| 1689 "return v;") |
| 1690 code.putln( |
| 1691 "}") |
| 1692 |
| 1693 def generate_setattro_function(self, scope, code): |
| 1694 # Setting and deleting an attribute are both done through |
| 1695 # the setattro method, so we dispatch to user's __setattr__ |
| 1696 # or __delattr__ or fall back on PyObject_GenericSetAttr. |
| 1697 base_type = scope.parent_type.base_type |
| 1698 set_entry = scope.lookup_here("__setattr__") |
| 1699 del_entry = scope.lookup_here("__delattr__") |
| 1700 code.putln("") |
| 1701 code.putln( |
| 1702 "static int %s(PyObject *o, PyObject *n, PyObject *v) {" % |
| 1703 scope.mangle_internal("tp_setattro")) |
| 1704 code.putln( |
| 1705 "if (v) {") |
| 1706 if set_entry: |
| 1707 code.putln( |
| 1708 "return %s(o, n, v);" % |
| 1709 set_entry.func_cname) |
| 1710 else: |
| 1711 self.generate_guarded_basetype_call( |
| 1712 base_type, None, "tp_setattro", "o, n, v", code) |
| 1713 code.putln( |
| 1714 "return PyObject_GenericSetAttr(o, n, v);") |
| 1715 code.putln( |
| 1716 "}") |
| 1717 code.putln( |
| 1718 "else {") |
| 1719 if del_entry: |
| 1720 code.putln( |
| 1721 "return %s(o, n);" % |
| 1722 del_entry.func_cname) |
| 1723 else: |
| 1724 self.generate_guarded_basetype_call( |
| 1725 base_type, None, "tp_setattro", "o, n, v", code) |
| 1726 code.putln( |
| 1727 "return PyObject_GenericSetAttr(o, n, 0);") |
| 1728 code.putln( |
| 1729 "}") |
| 1730 code.putln( |
| 1731 "}") |
| 1732 |
| 1733 def generate_descr_get_function(self, scope, code): |
| 1734 # The __get__ function of a descriptor object can be |
| 1735 # called with NULL for the second or third arguments |
| 1736 # under some circumstances, so we replace them with |
| 1737 # None in that case. |
| 1738 user_get_entry = scope.lookup_here("__get__") |
| 1739 code.putln("") |
| 1740 code.putln( |
| 1741 "static PyObject *%s(PyObject *o, PyObject *i, PyObject *c) {" % |
| 1742 scope.mangle_internal("tp_descr_get")) |
| 1743 code.putln( |
| 1744 "PyObject *r = 0;") |
| 1745 code.putln( |
| 1746 "if (!i) i = Py_None;") |
| 1747 code.putln( |
| 1748 "if (!c) c = Py_None;") |
| 1749 #code.put_incref("i", py_object_type) |
| 1750 #code.put_incref("c", py_object_type) |
| 1751 code.putln( |
| 1752 "r = %s(o, i, c);" % |
| 1753 user_get_entry.func_cname) |
| 1754 #code.put_decref("i", py_object_type) |
| 1755 #code.put_decref("c", py_object_type) |
| 1756 code.putln( |
| 1757 "return r;") |
| 1758 code.putln( |
| 1759 "}") |
| 1760 |
| 1761 def generate_descr_set_function(self, scope, code): |
| 1762 # Setting and deleting are both done through the __set__ |
| 1763 # method of a descriptor, so we dispatch to user's __set__ |
| 1764 # or __delete__ or raise an exception. |
| 1765 base_type = scope.parent_type.base_type |
| 1766 user_set_entry = scope.lookup_here("__set__") |
| 1767 user_del_entry = scope.lookup_here("__delete__") |
| 1768 code.putln("") |
| 1769 code.putln( |
| 1770 "static int %s(PyObject *o, PyObject *i, PyObject *v) {" % |
| 1771 scope.mangle_internal("tp_descr_set")) |
| 1772 code.putln( |
| 1773 "if (v) {") |
| 1774 if user_set_entry: |
| 1775 code.putln( |
| 1776 "return %s(o, i, v);" % |
| 1777 user_set_entry.func_cname) |
| 1778 else: |
| 1779 self.generate_guarded_basetype_call( |
| 1780 base_type, None, "tp_descr_set", "o, i, v", code) |
| 1781 code.putln( |
| 1782 'PyErr_SetString(PyExc_NotImplementedError, "__set__");') |
| 1783 code.putln( |
| 1784 "return -1;") |
| 1785 code.putln( |
| 1786 "}") |
| 1787 code.putln( |
| 1788 "else {") |
| 1789 if user_del_entry: |
| 1790 code.putln( |
| 1791 "return %s(o, i);" % |
| 1792 user_del_entry.func_cname) |
| 1793 else: |
| 1794 self.generate_guarded_basetype_call( |
| 1795 base_type, None, "tp_descr_set", "o, i, v", code) |
| 1796 code.putln( |
| 1797 'PyErr_SetString(PyExc_NotImplementedError, "__delete__");') |
| 1798 code.putln( |
| 1799 "return -1;") |
| 1800 code.putln( |
| 1801 "}") |
| 1802 code.putln( |
| 1803 "}") |
| 1804 |
| 1805 def generate_property_accessors(self, cclass_scope, code): |
| 1806 for entry in cclass_scope.property_entries: |
| 1807 property_scope = entry.scope |
| 1808 if property_scope.defines_any(["__get__"]): |
| 1809 self.generate_property_get_function(entry, code) |
| 1810 if property_scope.defines_any(["__set__", "__del__"]): |
| 1811 self.generate_property_set_function(entry, code) |
| 1812 |
| 1813 def generate_property_get_function(self, property_entry, code): |
| 1814 property_scope = property_entry.scope |
| 1815 property_entry.getter_cname = property_scope.parent_scope.mangle( |
| 1816 Naming.prop_get_prefix, property_entry.name) |
| 1817 get_entry = property_scope.lookup_here("__get__") |
| 1818 code.putln("") |
| 1819 code.putln( |
| 1820 "static PyObject *%s(PyObject *o, CYTHON_UNUSED void *x) {" % |
| 1821 property_entry.getter_cname) |
| 1822 code.putln( |
| 1823 "return %s(o);" % |
| 1824 get_entry.func_cname) |
| 1825 code.putln( |
| 1826 "}") |
| 1827 |
| 1828 def generate_property_set_function(self, property_entry, code): |
| 1829 property_scope = property_entry.scope |
| 1830 property_entry.setter_cname = property_scope.parent_scope.mangle( |
| 1831 Naming.prop_set_prefix, property_entry.name) |
| 1832 set_entry = property_scope.lookup_here("__set__") |
| 1833 del_entry = property_scope.lookup_here("__del__") |
| 1834 code.putln("") |
| 1835 code.putln( |
| 1836 "static int %s(PyObject *o, PyObject *v, CYTHON_UNUSED void *x) {" % |
| 1837 property_entry.setter_cname) |
| 1838 code.putln( |
| 1839 "if (v) {") |
| 1840 if set_entry: |
| 1841 code.putln( |
| 1842 "return %s(o, v);" % |
| 1843 set_entry.func_cname) |
| 1844 else: |
| 1845 code.putln( |
| 1846 'PyErr_SetString(PyExc_NotImplementedError, "__set__");') |
| 1847 code.putln( |
| 1848 "return -1;") |
| 1849 code.putln( |
| 1850 "}") |
| 1851 code.putln( |
| 1852 "else {") |
| 1853 if del_entry: |
| 1854 code.putln( |
| 1855 "return %s(o);" % |
| 1856 del_entry.func_cname) |
| 1857 else: |
| 1858 code.putln( |
| 1859 'PyErr_SetString(PyExc_NotImplementedError, "__del__");') |
| 1860 code.putln( |
| 1861 "return -1;") |
| 1862 code.putln( |
| 1863 "}") |
| 1864 code.putln( |
| 1865 "}") |
| 1866 |
| 1867 def generate_typeobj_definition(self, modname, entry, code): |
| 1868 type = entry.type |
| 1869 scope = type.scope |
| 1870 for suite in TypeSlots.substructures: |
| 1871 suite.generate_substructure(scope, code) |
| 1872 code.putln("") |
| 1873 if entry.visibility == 'public': |
| 1874 header = "DL_EXPORT(PyTypeObject) %s = {" |
| 1875 else: |
| 1876 header = "static PyTypeObject %s = {" |
| 1877 #code.putln(header % scope.parent_type.typeobj_cname) |
| 1878 code.putln(header % type.typeobj_cname) |
| 1879 code.putln( |
| 1880 "PyVarObject_HEAD_INIT(0, 0)") |
| 1881 code.putln( |
| 1882 '__Pyx_NAMESTR("%s.%s"), /*tp_name*/' % ( |
| 1883 self.full_module_name, scope.class_name)) |
| 1884 if type.typedef_flag: |
| 1885 objstruct = type.objstruct_cname |
| 1886 else: |
| 1887 objstruct = "struct %s" % type.objstruct_cname |
| 1888 code.putln( |
| 1889 "sizeof(%s), /*tp_basicsize*/" % |
| 1890 objstruct) |
| 1891 code.putln( |
| 1892 "0, /*tp_itemsize*/") |
| 1893 for slot in TypeSlots.slot_table: |
| 1894 slot.generate(scope, code) |
| 1895 code.putln( |
| 1896 "};") |
| 1897 |
| 1898 def generate_method_table(self, env, code): |
| 1899 if env.is_c_class_scope and not env.pyfunc_entries: |
| 1900 return |
| 1901 code.putln("") |
| 1902 code.putln( |
| 1903 "static PyMethodDef %s[] = {" % |
| 1904 env.method_table_cname) |
| 1905 for entry in env.pyfunc_entries: |
| 1906 if not entry.fused_cfunction: |
| 1907 code.put_pymethoddef(entry, ",") |
| 1908 code.putln( |
| 1909 "{0, 0, 0, 0}") |
| 1910 code.putln( |
| 1911 "};") |
| 1912 |
| 1913 def generate_getset_table(self, env, code): |
| 1914 if env.property_entries: |
| 1915 code.putln("") |
| 1916 code.putln( |
| 1917 "static struct PyGetSetDef %s[] = {" % |
| 1918 env.getset_table_cname) |
| 1919 for entry in env.property_entries: |
| 1920 if entry.doc: |
| 1921 doc_code = "__Pyx_DOCSTR(%s)" % code.get_string_const(entry.
doc) |
| 1922 else: |
| 1923 doc_code = "0" |
| 1924 code.putln( |
| 1925 '{(char *)"%s", %s, %s, %s, 0},' % ( |
| 1926 entry.name, |
| 1927 entry.getter_cname or "0", |
| 1928 entry.setter_cname or "0", |
| 1929 doc_code)) |
| 1930 code.putln( |
| 1931 "{0, 0, 0, 0, 0}") |
| 1932 code.putln( |
| 1933 "};") |
| 1934 |
| 1935 def generate_import_star(self, env, code): |
| 1936 env.use_utility_code(streq_utility_code) |
| 1937 code.putln() |
| 1938 code.putln("static char* %s_type_names[] = {" % Naming.import_star) |
| 1939 for name, entry in sorted(env.entries.items()): |
| 1940 if entry.is_type: |
| 1941 code.putln('"%s",' % name) |
| 1942 code.putln("0") |
| 1943 code.putln("};") |
| 1944 code.putln() |
| 1945 code.enter_cfunc_scope() # as we need labels |
| 1946 code.putln("static int %s(PyObject *o, PyObject* py_name, char *name) {"
% Naming.import_star_set) |
| 1947 code.putln("char** type_name = %s_type_names;" % Naming.import_star) |
| 1948 code.putln("while (*type_name) {") |
| 1949 code.putln("if (__Pyx_StrEq(name, *type_name)) {") |
| 1950 code.putln('PyErr_Format(PyExc_TypeError, "Cannot overwrite C type %s",
name);') |
| 1951 code.putln('goto bad;') |
| 1952 code.putln("}") |
| 1953 code.putln("type_name++;") |
| 1954 code.putln("}") |
| 1955 old_error_label = code.new_error_label() |
| 1956 code.putln("if (0);") # so the first one can be "else if" |
| 1957 for name, entry in env.entries.items(): |
| 1958 if entry.is_cglobal and entry.used: |
| 1959 code.putln('else if (__Pyx_StrEq(name, "%s")) {' % name) |
| 1960 if entry.type.is_pyobject: |
| 1961 if entry.type.is_extension_type or entry.type.is_builtin_typ
e: |
| 1962 code.putln("if (!(%s)) %s;" % ( |
| 1963 entry.type.type_test_code("o"), |
| 1964 code.error_goto(entry.pos))) |
| 1965 code.putln("Py_INCREF(o);") |
| 1966 code.put_decref(entry.cname, entry.type, nanny=False) |
| 1967 code.putln("%s = %s;" % ( |
| 1968 entry.cname, |
| 1969 PyrexTypes.typecast(entry.type, py_object_type, "o"))) |
| 1970 elif entry.type.from_py_function: |
| 1971 rhs = "%s(o)" % entry.type.from_py_function |
| 1972 if entry.type.is_enum: |
| 1973 rhs = PyrexTypes.typecast(entry.type, PyrexTypes.c_long_
type, rhs) |
| 1974 code.putln("%s = %s; if (%s) %s;" % ( |
| 1975 entry.cname, |
| 1976 rhs, |
| 1977 entry.type.error_condition(entry.cname), |
| 1978 code.error_goto(entry.pos))) |
| 1979 else: |
| 1980 code.putln('PyErr_Format(PyExc_TypeError, "Cannot convert Py
thon object %s to %s");' % (name, entry.type)) |
| 1981 code.putln(code.error_goto(entry.pos)) |
| 1982 code.putln("}") |
| 1983 code.putln("else {") |
| 1984 code.putln("if (PyObject_SetAttr(%s, py_name, o) < 0) goto bad;" % Namin
g.module_cname) |
| 1985 code.putln("}") |
| 1986 code.putln("return 0;") |
| 1987 if code.label_used(code.error_label): |
| 1988 code.put_label(code.error_label) |
| 1989 # This helps locate the offending name. |
| 1990 code.put_add_traceback(self.full_module_name) |
| 1991 code.error_label = old_error_label |
| 1992 code.putln("bad:") |
| 1993 code.putln("return -1;") |
| 1994 code.putln("}") |
| 1995 code.putln(import_star_utility_code) |
| 1996 code.exit_cfunc_scope() # done with labels |
| 1997 |
| 1998 def generate_module_init_func(self, imported_modules, env, code): |
| 1999 code.enter_cfunc_scope() |
| 2000 code.putln("") |
| 2001 header2 = "PyMODINIT_FUNC init%s(void)" % env.module_name |
| 2002 header3 = "PyMODINIT_FUNC PyInit_%s(void)" % env.module_name |
| 2003 code.putln("#if PY_MAJOR_VERSION < 3") |
| 2004 code.putln("%s; /*proto*/" % header2) |
| 2005 code.putln(header2) |
| 2006 code.putln("#else") |
| 2007 code.putln("%s; /*proto*/" % header3) |
| 2008 code.putln(header3) |
| 2009 code.putln("#endif") |
| 2010 code.putln("{") |
| 2011 tempdecl_code = code.insertion_point() |
| 2012 |
| 2013 code.put_declare_refcount_context() |
| 2014 code.putln("#if CYTHON_REFNANNY") |
| 2015 code.putln("__Pyx_RefNanny = __Pyx_RefNannyImportAPI(\"refnanny\");") |
| 2016 code.putln("if (!__Pyx_RefNanny) {") |
| 2017 code.putln(" PyErr_Clear();") |
| 2018 code.putln(" __Pyx_RefNanny = __Pyx_RefNannyImportAPI(\"Cython.Runtime.
refnanny\");") |
| 2019 code.putln(" if (!__Pyx_RefNanny)") |
| 2020 code.putln(" Py_FatalError(\"failed to import 'refnanny' module\");
") |
| 2021 code.putln("}") |
| 2022 code.putln("#endif") |
| 2023 code.put_setup_refcount_context(header3) |
| 2024 |
| 2025 env.use_utility_code(UtilityCode.load("CheckBinaryVersion", "ModuleSetup
Code.c")) |
| 2026 code.putln("if ( __Pyx_check_binary_version() < 0) %s" % code.error_goto
(self.pos)) |
| 2027 |
| 2028 code.putln("%s = PyTuple_New(0); %s" % (Naming.empty_tuple, code.error_g
oto_if_null(Naming.empty_tuple, self.pos))) |
| 2029 code.putln("%s = PyBytes_FromStringAndSize(\"\", 0); %s" % (Naming.empty
_bytes, code.error_goto_if_null(Naming.empty_bytes, self.pos))) |
| 2030 |
| 2031 code.putln("#ifdef __Pyx_CyFunction_USED") |
| 2032 code.putln("if (__Pyx_CyFunction_init() < 0) %s" % code.error_goto(self.
pos)) |
| 2033 code.putln("#endif") |
| 2034 |
| 2035 code.putln("#ifdef __Pyx_FusedFunction_USED") |
| 2036 code.putln("if (__pyx_FusedFunction_init() < 0) %s" % code.error_goto(se
lf.pos)) |
| 2037 code.putln("#endif") |
| 2038 |
| 2039 code.putln("#ifdef __Pyx_Generator_USED") |
| 2040 code.putln("if (__pyx_Generator_init() < 0) %s" % code.error_goto(self.p
os)) |
| 2041 code.putln("#endif") |
| 2042 |
| 2043 code.putln("/*--- Library function declarations ---*/") |
| 2044 env.generate_library_function_declarations(code) |
| 2045 |
| 2046 code.putln("/*--- Threads initialization code ---*/") |
| 2047 code.putln("#if defined(__PYX_FORCE_INIT_THREADS) && __PYX_FORCE_INIT_TH
READS") |
| 2048 code.putln("#ifdef WITH_THREAD /* Python build with threading support? *
/") |
| 2049 code.putln("PyEval_InitThreads();") |
| 2050 code.putln("#endif") |
| 2051 code.putln("#endif") |
| 2052 |
| 2053 code.putln("/*--- Module creation code ---*/") |
| 2054 self.generate_module_creation_code(env, code) |
| 2055 |
| 2056 code.putln("/*--- Initialize various global constants etc. ---*/") |
| 2057 code.putln(code.error_goto_if_neg("__Pyx_InitGlobals()", self.pos)) |
| 2058 |
| 2059 code.putln("#if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_I
S_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT)") |
| 2060 code.putln("if (__Pyx_init_sys_getdefaultencoding_params() < 0) %s" % co
de.error_goto(self.pos)) |
| 2061 code.putln("#endif") |
| 2062 |
| 2063 __main__name = code.globalstate.get_py_string_const( |
| 2064 EncodedString("__main__"), identifier=True) |
| 2065 code.putln("if (%s%s) {" % (Naming.module_is_main, self.full_module_name
.replace('.', '__'))) |
| 2066 code.putln( |
| 2067 'if (__Pyx_SetAttrString(%s, "__name__", %s) < 0) %s;' % ( |
| 2068 env.module_cname, |
| 2069 __main__name.cname, |
| 2070 code.error_goto(self.pos))) |
| 2071 code.putln("}") |
| 2072 |
| 2073 # set up __file__ and __path__, then add the module to sys.modules |
| 2074 self.generate_module_import_setup(env, code) |
| 2075 |
| 2076 if Options.cache_builtins: |
| 2077 code.putln("/*--- Builtin init code ---*/") |
| 2078 code.putln(code.error_goto_if_neg("__Pyx_InitCachedBuiltins()", self
.pos)) |
| 2079 |
| 2080 code.putln("/*--- Constants init code ---*/") |
| 2081 code.putln(code.error_goto_if_neg("__Pyx_InitCachedConstants()", self.po
s)) |
| 2082 |
| 2083 code.putln("/*--- Global init code ---*/") |
| 2084 self.generate_global_init_code(env, code) |
| 2085 |
| 2086 code.putln("/*--- Variable export code ---*/") |
| 2087 self.generate_c_variable_export_code(env, code) |
| 2088 |
| 2089 code.putln("/*--- Function export code ---*/") |
| 2090 self.generate_c_function_export_code(env, code) |
| 2091 |
| 2092 code.putln("/*--- Type init code ---*/") |
| 2093 self.generate_type_init_code(env, code) |
| 2094 |
| 2095 code.putln("/*--- Type import code ---*/") |
| 2096 for module in imported_modules: |
| 2097 self.generate_type_import_code_for_module(module, env, code) |
| 2098 |
| 2099 code.putln("/*--- Variable import code ---*/") |
| 2100 for module in imported_modules: |
| 2101 self.generate_c_variable_import_code_for_module(module, env, code) |
| 2102 |
| 2103 code.putln("/*--- Function import code ---*/") |
| 2104 for module in imported_modules: |
| 2105 self.specialize_fused_types(module) |
| 2106 self.generate_c_function_import_code_for_module(module, env, code) |
| 2107 |
| 2108 code.putln("/*--- Execution code ---*/") |
| 2109 code.mark_pos(None) |
| 2110 |
| 2111 self.body.generate_execution_code(code) |
| 2112 |
| 2113 if Options.generate_cleanup_code: |
| 2114 code.globalstate.use_utility_code( |
| 2115 UtilityCode.load_cached("RegisterModuleCleanup", "ModuleSetupCod
e.c")) |
| 2116 code.putln("if (__Pyx_RegisterCleanup()) %s;" % code.error_goto(self
.pos)) |
| 2117 |
| 2118 code.put_goto(code.return_label) |
| 2119 code.put_label(code.error_label) |
| 2120 for cname, type in code.funcstate.all_managed_temps(): |
| 2121 code.put_xdecref(cname, type) |
| 2122 code.putln('if (%s) {' % env.module_cname) |
| 2123 code.put_add_traceback("init %s" % env.qualified_name) |
| 2124 env.use_utility_code(Nodes.traceback_utility_code) |
| 2125 code.put_decref_clear(env.module_cname, py_object_type, nanny=False) |
| 2126 code.putln('} else if (!PyErr_Occurred()) {') |
| 2127 code.putln('PyErr_SetString(PyExc_ImportError, "init %s");' % env.qualif
ied_name) |
| 2128 code.putln('}') |
| 2129 code.put_label(code.return_label) |
| 2130 |
| 2131 code.put_finish_refcount_context() |
| 2132 |
| 2133 code.putln("#if PY_MAJOR_VERSION < 3") |
| 2134 code.putln("return;") |
| 2135 code.putln("#else") |
| 2136 code.putln("return %s;" % env.module_cname) |
| 2137 code.putln("#endif") |
| 2138 code.putln('}') |
| 2139 |
| 2140 tempdecl_code.put_temp_declarations(code.funcstate) |
| 2141 |
| 2142 code.exit_cfunc_scope() |
| 2143 |
| 2144 def generate_module_import_setup(self, env, code): |
| 2145 module_path = env.directives['set_initial_path'] |
| 2146 if module_path == 'SOURCEFILE': |
| 2147 module_path = self.pos[0].filename |
| 2148 |
| 2149 if module_path: |
| 2150 code.putln('if (__Pyx_SetAttrString(%s, "__file__", %s) < 0) %s;' %
( |
| 2151 env.module_cname, |
| 2152 code.globalstate.get_py_string_const( |
| 2153 EncodedString(decode_filename(module_path))).cname, |
| 2154 code.error_goto(self.pos))) |
| 2155 |
| 2156 if env.is_package: |
| 2157 # set __path__ to mark the module as package |
| 2158 temp = code.funcstate.allocate_temp(py_object_type, True) |
| 2159 code.putln('%s = Py_BuildValue("[O]", %s); %s' % ( |
| 2160 temp, |
| 2161 code.globalstate.get_py_string_const( |
| 2162 EncodedString(decode_filename( |
| 2163 os.path.dirname(module_path)))).cname, |
| 2164 code.error_goto_if_null(temp, self.pos))) |
| 2165 code.put_gotref(temp) |
| 2166 code.putln( |
| 2167 'if (__Pyx_SetAttrString(%s, "__path__", %s) < 0) %s;' % ( |
| 2168 env.module_cname, temp, code.error_goto(self.pos))) |
| 2169 code.put_decref_clear(temp, py_object_type) |
| 2170 code.funcstate.release_temp(temp) |
| 2171 |
| 2172 elif env.is_package: |
| 2173 # packages require __path__, so all we can do is try to figure |
| 2174 # out the module path at runtime by rerunning the import lookup |
| 2175 package_name, _ = self.full_module_name.rsplit('.', 1) |
| 2176 if '.' in package_name: |
| 2177 parent_name = '"%s"' % (package_name.rsplit('.', 1)[0],) |
| 2178 else: |
| 2179 parent_name = 'NULL' |
| 2180 code.globalstate.use_utility_code(UtilityCode.load( |
| 2181 "SetPackagePathFromImportLib", "ImportExport.c")) |
| 2182 code.putln(code.error_goto_if_neg( |
| 2183 '__Pyx_SetPackagePathFromImportLib(%s, %s)' % ( |
| 2184 parent_name, |
| 2185 code.globalstate.get_py_string_const( |
| 2186 EncodedString(env.module_name)).cname), |
| 2187 self.pos)) |
| 2188 |
| 2189 # CPython may not have put us into sys.modules yet, but relative imports
and reimports require it |
| 2190 fq_module_name = self.full_module_name |
| 2191 if fq_module_name.endswith('.__init__'): |
| 2192 fq_module_name = fq_module_name[:-len('.__init__')] |
| 2193 code.putln("#if PY_MAJOR_VERSION >= 3") |
| 2194 code.putln("{") |
| 2195 code.putln("PyObject *modules = PyImport_GetModuleDict(); %s" % |
| 2196 code.error_goto_if_null("modules", self.pos)) |
| 2197 code.putln('if (!PyDict_GetItemString(modules, "%s")) {' % fq_module_nam
e) |
| 2198 code.putln(code.error_goto_if_neg('PyDict_SetItemString(modules, "%s", %
s)' % ( |
| 2199 fq_module_name, env.module_cname), self.pos)) |
| 2200 code.putln("}") |
| 2201 code.putln("}") |
| 2202 code.putln("#endif") |
| 2203 |
| 2204 def generate_module_cleanup_func(self, env, code): |
| 2205 if not Options.generate_cleanup_code: |
| 2206 return |
| 2207 |
| 2208 code.putln('static void %s(CYTHON_UNUSED PyObject *self) {' % |
| 2209 Naming.cleanup_cname) |
| 2210 if Options.generate_cleanup_code >= 2: |
| 2211 code.putln("/*--- Global cleanup code ---*/") |
| 2212 rev_entries = list(env.var_entries) |
| 2213 rev_entries.reverse() |
| 2214 for entry in rev_entries: |
| 2215 if entry.visibility != 'extern': |
| 2216 if entry.type.is_pyobject and entry.used: |
| 2217 code.put_xdecref_clear( |
| 2218 entry.cname, entry.type, |
| 2219 clear_before_decref=True, |
| 2220 nanny=False) |
| 2221 code.putln("__Pyx_CleanupGlobals();") |
| 2222 if Options.generate_cleanup_code >= 3: |
| 2223 code.putln("/*--- Type import cleanup code ---*/") |
| 2224 for ext_type in sorted(env.types_imported, key=operator.attrgetter('
typeptr_cname')): |
| 2225 code.put_xdecref_clear( |
| 2226 ext_type.typeptr_cname, ext_type, |
| 2227 clear_before_decref=True, |
| 2228 nanny=False) |
| 2229 if Options.cache_builtins: |
| 2230 code.putln("/*--- Builtin cleanup code ---*/") |
| 2231 for entry in env.cached_builtins: |
| 2232 code.put_xdecref_clear( |
| 2233 entry.cname, PyrexTypes.py_object_type, |
| 2234 clear_before_decref=True, |
| 2235 nanny=False) |
| 2236 code.putln("/*--- Intern cleanup code ---*/") |
| 2237 code.put_decref_clear(Naming.empty_tuple, |
| 2238 PyrexTypes.py_object_type, |
| 2239 clear_before_decref=True, |
| 2240 nanny=False) |
| 2241 for entry in env.c_class_entries: |
| 2242 cclass_type = entry.type |
| 2243 if cclass_type.is_external or cclass_type.base_type: |
| 2244 continue |
| 2245 if cclass_type.scope.directives.get('freelist', 0): |
| 2246 scope = cclass_type.scope |
| 2247 freelist_name = scope.mangle_internal(Naming.freelist_name) |
| 2248 freecount_name = scope.mangle_internal(Naming.freecount_name) |
| 2249 code.putln("while (%s > 0) {" % freecount_name) |
| 2250 code.putln("PyObject* o = (PyObject*)%s[--%s];" % ( |
| 2251 freelist_name, freecount_name)) |
| 2252 code.putln("(*Py_TYPE(o)->tp_free)(o);") |
| 2253 code.putln("}") |
| 2254 # for entry in env.pynum_entries: |
| 2255 # code.put_decref_clear(entry.cname, |
| 2256 # PyrexTypes.py_object_type, |
| 2257 # nanny=False) |
| 2258 # for entry in env.all_pystring_entries: |
| 2259 # if entry.is_interned: |
| 2260 # code.put_decref_clear(entry.pystring_cname, |
| 2261 # PyrexTypes.py_object_type, |
| 2262 # nanny=False) |
| 2263 # for entry in env.default_entries: |
| 2264 # if entry.type.is_pyobject and entry.used: |
| 2265 # code.putln("Py_DECREF(%s); %s = 0;" % ( |
| 2266 # code.entry_as_pyobject(entry), entry.cname)) |
| 2267 code.putln('#if CYTHON_COMPILING_IN_PYPY') |
| 2268 code.putln('Py_CLEAR(%s);' % Naming.builtins_cname) |
| 2269 code.putln('#endif') |
| 2270 code.put_decref_clear(env.module_dict_cname, py_object_type, |
| 2271 nanny=False, clear_before_decref=True) |
| 2272 |
| 2273 def generate_main_method(self, env, code): |
| 2274 module_is_main = "%s%s" % (Naming.module_is_main, self.full_module_name.
replace('.', '__')) |
| 2275 if Options.embed == "main": |
| 2276 wmain = "wmain" |
| 2277 else: |
| 2278 wmain = Options.embed |
| 2279 code.globalstate.use_utility_code( |
| 2280 main_method.specialize( |
| 2281 module_name = env.module_name, |
| 2282 module_is_main = module_is_main, |
| 2283 main_method = Options.embed, |
| 2284 wmain_method = wmain)) |
| 2285 |
| 2286 def generate_pymoduledef_struct(self, env, code): |
| 2287 if env.doc: |
| 2288 doc = "__Pyx_DOCSTR(%s)" % code.get_string_const(env.doc) |
| 2289 else: |
| 2290 doc = "0" |
| 2291 if Options.generate_cleanup_code: |
| 2292 cleanup_func = "(freefunc)%s" % Naming.cleanup_cname |
| 2293 else: |
| 2294 cleanup_func = 'NULL' |
| 2295 |
| 2296 code.putln("") |
| 2297 code.putln("#if PY_MAJOR_VERSION >= 3") |
| 2298 code.putln("static struct PyModuleDef %s = {" % Naming.pymoduledef_cname
) |
| 2299 code.putln("#if PY_VERSION_HEX < 0x03020000") |
| 2300 # fix C compiler warnings due to missing initialisers |
| 2301 code.putln(" { PyObject_HEAD_INIT(NULL) NULL, 0, NULL },") |
| 2302 code.putln("#else") |
| 2303 code.putln(" PyModuleDef_HEAD_INIT,") |
| 2304 code.putln("#endif") |
| 2305 code.putln(' __Pyx_NAMESTR("%s"),' % env.module_name) |
| 2306 code.putln(" %s, /* m_doc */" % doc) |
| 2307 code.putln(" -1, /* m_size */") |
| 2308 code.putln(" %s /* m_methods */," % env.method_table_cname) |
| 2309 code.putln(" NULL, /* m_reload */") |
| 2310 code.putln(" NULL, /* m_traverse */") |
| 2311 code.putln(" NULL, /* m_clear */") |
| 2312 code.putln(" %s /* m_free */" % cleanup_func) |
| 2313 code.putln("};") |
| 2314 code.putln("#endif") |
| 2315 |
| 2316 def generate_module_creation_code(self, env, code): |
| 2317 # Generate code to create the module object and |
| 2318 # install the builtins. |
| 2319 if env.doc: |
| 2320 doc = "__Pyx_DOCSTR(%s)" % code.get_string_const(env.doc) |
| 2321 else: |
| 2322 doc = "0" |
| 2323 code.putln("#if PY_MAJOR_VERSION < 3") |
| 2324 code.putln( |
| 2325 '%s = Py_InitModule4(__Pyx_NAMESTR("%s"), %s, %s, 0, PYTHON_API_VERS
ION); Py_XINCREF(%s);' % ( |
| 2326 env.module_cname, |
| 2327 env.module_name, |
| 2328 env.method_table_cname, |
| 2329 doc, |
| 2330 env.module_cname)) |
| 2331 code.putln("#else") |
| 2332 code.putln( |
| 2333 "%s = PyModule_Create(&%s);" % ( |
| 2334 env.module_cname, |
| 2335 Naming.pymoduledef_cname)) |
| 2336 code.putln("#endif") |
| 2337 code.putln(code.error_goto_if_null(env.module_cname, self.pos)) |
| 2338 code.putln( |
| 2339 "%s = PyModule_GetDict(%s); %s" % ( |
| 2340 env.module_dict_cname, env.module_cname, |
| 2341 code.error_goto_if_null(env.module_dict_cname, self.pos))) |
| 2342 code.put_incref(env.module_dict_cname, py_object_type, nanny=False) |
| 2343 |
| 2344 code.putln( |
| 2345 '%s = PyImport_AddModule(__Pyx_NAMESTR(__Pyx_BUILTIN_MODULE_NAME));
%s' % ( |
| 2346 Naming.builtins_cname, |
| 2347 code.error_goto_if_null(Naming.builtins_cname, self.pos))) |
| 2348 code.putln('#if CYTHON_COMPILING_IN_PYPY') |
| 2349 code.putln('Py_INCREF(%s);' % Naming.builtins_cname) |
| 2350 code.putln('#endif') |
| 2351 code.putln( |
| 2352 'if (__Pyx_SetAttrString(%s, "__builtins__", %s) < 0) %s;' % ( |
| 2353 env.module_cname, |
| 2354 Naming.builtins_cname, |
| 2355 code.error_goto(self.pos))) |
| 2356 if Options.pre_import is not None: |
| 2357 code.putln( |
| 2358 '%s = PyImport_AddModule(__Pyx_NAMESTR("%s")); %s' % ( |
| 2359 Naming.preimport_cname, |
| 2360 Options.pre_import, |
| 2361 code.error_goto_if_null(Naming.preimport_cname, self.pos))) |
| 2362 |
| 2363 def generate_global_init_code(self, env, code): |
| 2364 # Generate code to initialise global PyObject * |
| 2365 # variables to None. |
| 2366 for entry in env.var_entries: |
| 2367 if entry.visibility != 'extern': |
| 2368 if entry.used: |
| 2369 entry.type.global_init_code(entry, code) |
| 2370 |
| 2371 def generate_c_variable_export_code(self, env, code): |
| 2372 # Generate code to create PyCFunction wrappers for exported C functions. |
| 2373 entries = [] |
| 2374 for entry in env.var_entries: |
| 2375 if (entry.api |
| 2376 or entry.defined_in_pxd |
| 2377 or (Options.cimport_from_pyx and not entry.visibility == 'extern
')): |
| 2378 entries.append(entry) |
| 2379 if entries: |
| 2380 env.use_utility_code(UtilityCode.load_cached("VoidPtrExport", "Impor
tExport.c")) |
| 2381 for entry in entries: |
| 2382 signature = entry.type.declaration_code("") |
| 2383 name = code.intern_identifier(entry.name) |
| 2384 code.putln('if (__Pyx_ExportVoidPtr(%s, (void *)&%s, "%s") < 0)
%s' % ( |
| 2385 name, entry.cname, signature, |
| 2386 code.error_goto(self.pos))) |
| 2387 |
| 2388 def generate_c_function_export_code(self, env, code): |
| 2389 # Generate code to create PyCFunction wrappers for exported C functions. |
| 2390 entries = [] |
| 2391 for entry in env.cfunc_entries: |
| 2392 if (entry.api |
| 2393 or entry.defined_in_pxd |
| 2394 or (Options.cimport_from_pyx and not entry.visibility == 'extern
')): |
| 2395 entries.append(entry) |
| 2396 if entries: |
| 2397 env.use_utility_code( |
| 2398 UtilityCode.load_cached("FunctionExport", "ImportExport.c")) |
| 2399 for entry in entries: |
| 2400 signature = entry.type.signature_string() |
| 2401 code.putln('if (__Pyx_ExportFunction("%s", (void (*)(void))%s, "
%s") < 0) %s' % ( |
| 2402 entry.name, |
| 2403 entry.cname, |
| 2404 signature, |
| 2405 code.error_goto(self.pos))) |
| 2406 |
| 2407 def generate_type_import_code_for_module(self, module, env, code): |
| 2408 # Generate type import code for all exported extension types in |
| 2409 # an imported module. |
| 2410 #if module.c_class_entries: |
| 2411 for entry in module.c_class_entries: |
| 2412 if entry.defined_in_pxd: |
| 2413 self.generate_type_import_code(env, entry.type, entry.pos, code) |
| 2414 |
| 2415 def specialize_fused_types(self, pxd_env): |
| 2416 """ |
| 2417 If fused c(p)def functions are defined in an imported pxd, but not |
| 2418 used in this implementation file, we still have fused entries and |
| 2419 not specialized ones. This method replaces any fused entries with their |
| 2420 specialized ones. |
| 2421 """ |
| 2422 for entry in pxd_env.cfunc_entries[:]: |
| 2423 if entry.type.is_fused: |
| 2424 # This call modifies the cfunc_entries in-place |
| 2425 entry.type.get_all_specialized_function_types() |
| 2426 |
| 2427 def generate_c_variable_import_code_for_module(self, module, env, code): |
| 2428 # Generate import code for all exported C functions in a cimported modul
e. |
| 2429 entries = [] |
| 2430 for entry in module.var_entries: |
| 2431 if entry.defined_in_pxd: |
| 2432 entries.append(entry) |
| 2433 if entries: |
| 2434 env.use_utility_code( |
| 2435 UtilityCode.load_cached("ModuleImport", "ImportExport.c")) |
| 2436 env.use_utility_code( |
| 2437 UtilityCode.load_cached("VoidPtrImport", "ImportExport.c")) |
| 2438 temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True) |
| 2439 code.putln( |
| 2440 '%s = __Pyx_ImportModule("%s"); if (!%s) %s' % ( |
| 2441 temp, |
| 2442 module.qualified_name, |
| 2443 temp, |
| 2444 code.error_goto(self.pos))) |
| 2445 for entry in entries: |
| 2446 if env is module: |
| 2447 cname = entry.cname |
| 2448 else: |
| 2449 cname = module.mangle(Naming.varptr_prefix, entry.name) |
| 2450 signature = entry.type.declaration_code("") |
| 2451 code.putln( |
| 2452 'if (__Pyx_ImportVoidPtr(%s, "%s", (void **)&%s, "%s") < 0)
%s' % ( |
| 2453 temp, entry.name, cname, signature, |
| 2454 code.error_goto(self.pos))) |
| 2455 code.putln("Py_DECREF(%s); %s = 0;" % (temp, temp)) |
| 2456 |
| 2457 def generate_c_function_import_code_for_module(self, module, env, code): |
| 2458 # Generate import code for all exported C functions in a cimported modul
e. |
| 2459 entries = [] |
| 2460 for entry in module.cfunc_entries: |
| 2461 if entry.defined_in_pxd and entry.used: |
| 2462 entries.append(entry) |
| 2463 if entries: |
| 2464 env.use_utility_code( |
| 2465 UtilityCode.load_cached("ModuleImport", "ImportExport.c")) |
| 2466 env.use_utility_code( |
| 2467 UtilityCode.load_cached("FunctionImport", "ImportExport.c")) |
| 2468 temp = code.funcstate.allocate_temp(py_object_type, manage_ref=True) |
| 2469 code.putln( |
| 2470 '%s = __Pyx_ImportModule("%s"); if (!%s) %s' % ( |
| 2471 temp, |
| 2472 module.qualified_name, |
| 2473 temp, |
| 2474 code.error_goto(self.pos))) |
| 2475 for entry in entries: |
| 2476 code.putln( |
| 2477 'if (__Pyx_ImportFunction(%s, "%s", (void (**)(void))&%s, "%
s") < 0) %s' % ( |
| 2478 temp, |
| 2479 entry.name, |
| 2480 entry.cname, |
| 2481 entry.type.signature_string(), |
| 2482 code.error_goto(self.pos))) |
| 2483 code.putln("Py_DECREF(%s); %s = 0;" % (temp, temp)) |
| 2484 |
| 2485 def generate_type_init_code(self, env, code): |
| 2486 # Generate type import code for extern extension types |
| 2487 # and type ready code for non-extern ones. |
| 2488 for entry in env.c_class_entries: |
| 2489 if entry.visibility == 'extern' and not entry.utility_code_definitio
n: |
| 2490 self.generate_type_import_code(env, entry.type, entry.pos, code) |
| 2491 else: |
| 2492 self.generate_base_type_import_code(env, entry, code) |
| 2493 self.generate_exttype_vtable_init_code(entry, code) |
| 2494 self.generate_type_ready_code(env, entry, code) |
| 2495 self.generate_typeptr_assignment_code(entry, code) |
| 2496 |
| 2497 def generate_base_type_import_code(self, env, entry, code): |
| 2498 base_type = entry.type.base_type |
| 2499 if (base_type and base_type.module_name != env.qualified_name and not |
| 2500 base_type.is_builtin_type and not entry.utility_code_definition): |
| 2501 self.generate_type_import_code(env, base_type, self.pos, code) |
| 2502 |
| 2503 def generate_type_import_code(self, env, type, pos, code): |
| 2504 # If not already done, generate code to import the typeobject of an |
| 2505 # extension type defined in another module, and extract its C method |
| 2506 # table pointer if any. |
| 2507 if type in env.types_imported: |
| 2508 return |
| 2509 env.use_utility_code(UtilityCode.load_cached("TypeImport", "ImportExport
.c")) |
| 2510 self.generate_type_import_call(type, code, |
| 2511 code.error_goto_if_null(type.typeptr_cnam
e, pos)) |
| 2512 if type.vtabptr_cname: |
| 2513 code.globalstate.use_utility_code( |
| 2514 UtilityCode.load_cached('GetVTable', 'ImportExport.c')) |
| 2515 code.putln("%s = (struct %s*)__Pyx_GetVtable(%s->tp_dict); %s" % ( |
| 2516 type.vtabptr_cname, |
| 2517 type.vtabstruct_cname, |
| 2518 type.typeptr_cname, |
| 2519 code.error_goto_if_null(type.vtabptr_cname, pos))) |
| 2520 env.types_imported.add(type) |
| 2521 |
| 2522 py3_type_name_map = {'str' : 'bytes', 'unicode' : 'str'} |
| 2523 |
| 2524 def generate_type_import_call(self, type, code, error_code): |
| 2525 if type.typedef_flag: |
| 2526 objstruct = type.objstruct_cname |
| 2527 else: |
| 2528 objstruct = "struct %s" % type.objstruct_cname |
| 2529 sizeof_objstruct = objstruct |
| 2530 module_name = type.module_name |
| 2531 condition = replacement = None |
| 2532 if module_name not in ('__builtin__', 'builtins'): |
| 2533 module_name = '"%s"' % module_name |
| 2534 else: |
| 2535 module_name = '__Pyx_BUILTIN_MODULE_NAME' |
| 2536 if type.name in Code.non_portable_builtins_map: |
| 2537 condition, replacement = Code.non_portable_builtins_map[type.nam
e] |
| 2538 if objstruct in Code.basicsize_builtins_map: |
| 2539 # Some builtin types have a tp_basicsize which differs from size
of(...): |
| 2540 sizeof_objstruct = Code.basicsize_builtins_map[objstruct] |
| 2541 |
| 2542 code.put('%s = __Pyx_ImportType(%s,' % ( |
| 2543 type.typeptr_cname, |
| 2544 module_name)) |
| 2545 |
| 2546 if condition and replacement: |
| 2547 code.putln("") # start in new line |
| 2548 code.putln("#if %s" % condition) |
| 2549 code.putln('"%s",' % replacement) |
| 2550 code.putln("#else") |
| 2551 code.putln('"%s",' % type.name) |
| 2552 code.putln("#endif") |
| 2553 else: |
| 2554 code.put(' "%s", ' % type.name) |
| 2555 |
| 2556 if sizeof_objstruct != objstruct: |
| 2557 if not condition: |
| 2558 code.putln("") # start in new line |
| 2559 code.putln("#if CYTHON_COMPILING_IN_PYPY") |
| 2560 code.putln('sizeof(%s),' % objstruct) |
| 2561 code.putln("#else") |
| 2562 code.putln('sizeof(%s),' % sizeof_objstruct) |
| 2563 code.putln("#endif") |
| 2564 else: |
| 2565 code.put('sizeof(%s), ' % objstruct) |
| 2566 |
| 2567 code.putln('%i); %s' % ( |
| 2568 not type.is_external or type.is_subclassed, |
| 2569 error_code)) |
| 2570 |
| 2571 def generate_type_ready_code(self, env, entry, code): |
| 2572 # Generate a call to PyType_Ready for an extension |
| 2573 # type defined in this module. |
| 2574 type = entry.type |
| 2575 typeobj_cname = type.typeobj_cname |
| 2576 scope = type.scope |
| 2577 if scope: # could be None if there was an error |
| 2578 if entry.visibility != 'extern': |
| 2579 for slot in TypeSlots.slot_table: |
| 2580 slot.generate_dynamic_init_code(scope, code) |
| 2581 code.putln( |
| 2582 "if (PyType_Ready(&%s) < 0) %s" % ( |
| 2583 typeobj_cname, |
| 2584 code.error_goto(entry.pos))) |
| 2585 # Don't inherit tp_print from builtin types, restoring the |
| 2586 # behavior of using tp_repr or tp_str instead. |
| 2587 code.putln("%s.tp_print = 0;" % typeobj_cname) |
| 2588 # Fix special method docstrings. This is a bit of a hack, but |
| 2589 # unless we let PyType_Ready create the slot wrappers we have |
| 2590 # a significant performance hit. (See trac #561.) |
| 2591 for func in entry.type.scope.pyfunc_entries: |
| 2592 is_buffer = func.name in ('__getbuffer__', |
| 2593 '__releasebuffer__') |
| 2594 if (func.is_special and Options.docstrings and |
| 2595 func.wrapperbase_cname and not is_buffer): |
| 2596 slot = TypeSlots.method_name_to_slot[func.name] |
| 2597 preprocessor_guard = slot.preprocessor_guard_code() |
| 2598 if preprocessor_guard: |
| 2599 code.putln(preprocessor_guard) |
| 2600 code.putln('#if CYTHON_COMPILING_IN_CPYTHON') |
| 2601 code.putln("{") |
| 2602 code.putln( |
| 2603 'PyObject *wrapper = __Pyx_GetAttrString((PyObject *
)&%s, "%s"); %s' % ( |
| 2604 typeobj_cname, |
| 2605 func.name, |
| 2606 code.error_goto_if_null('wrapper', entry.pos))) |
| 2607 code.putln( |
| 2608 "if (Py_TYPE(wrapper) == &PyWrapperDescr_Type) {") |
| 2609 code.putln( |
| 2610 "%s = *((PyWrapperDescrObject *)wrapper)->d_base;" %
( |
| 2611 func.wrapperbase_cname)) |
| 2612 code.putln( |
| 2613 "%s.doc = %s;" % (func.wrapperbase_cname, func.doc_c
name)) |
| 2614 code.putln( |
| 2615 "((PyWrapperDescrObject *)wrapper)->d_base = &%s;" %
( |
| 2616 func.wrapperbase_cname)) |
| 2617 code.putln("}") |
| 2618 code.putln("}") |
| 2619 code.putln('#endif') |
| 2620 if preprocessor_guard: |
| 2621 code.putln('#endif') |
| 2622 if type.vtable_cname: |
| 2623 code.putln( |
| 2624 "if (__Pyx_SetVtable(%s.tp_dict, %s) < 0) %s" % ( |
| 2625 typeobj_cname, |
| 2626 type.vtabptr_cname, |
| 2627 code.error_goto(entry.pos))) |
| 2628 code.globalstate.use_utility_code( |
| 2629 UtilityCode.load_cached('SetVTable', 'ImportExport.c')) |
| 2630 if not type.scope.is_internal and not type.scope.directives['int
ernal']: |
| 2631 # scope.is_internal is set for types defined by |
| 2632 # Cython (such as closures), the 'internal' |
| 2633 # directive is set by users |
| 2634 code.putln( |
| 2635 'if (__Pyx_SetAttrString(%s, "%s", (PyObject *)&%s) < 0)
%s' % ( |
| 2636 Naming.module_cname, |
| 2637 scope.class_name, |
| 2638 typeobj_cname, |
| 2639 code.error_goto(entry.pos))) |
| 2640 weakref_entry = scope.lookup_here("__weakref__") |
| 2641 if weakref_entry: |
| 2642 if weakref_entry.type is py_object_type: |
| 2643 tp_weaklistoffset = "%s.tp_weaklistoffset" % typeobj_cna
me |
| 2644 if type.typedef_flag: |
| 2645 objstruct = type.objstruct_cname |
| 2646 else: |
| 2647 objstruct = "struct %s" % type.objstruct_cname |
| 2648 code.putln("if (%s == 0) %s = offsetof(%s, %s);" % ( |
| 2649 tp_weaklistoffset, |
| 2650 tp_weaklistoffset, |
| 2651 objstruct, |
| 2652 weakref_entry.cname)) |
| 2653 else: |
| 2654 error(weakref_entry.pos, "__weakref__ slot must be of ty
pe 'object'") |
| 2655 |
| 2656 def generate_exttype_vtable_init_code(self, entry, code): |
| 2657 # Generate code to initialise the C method table of an |
| 2658 # extension type. |
| 2659 type = entry.type |
| 2660 if type.vtable_cname: |
| 2661 code.putln( |
| 2662 "%s = &%s;" % ( |
| 2663 type.vtabptr_cname, |
| 2664 type.vtable_cname)) |
| 2665 if type.base_type and type.base_type.vtabptr_cname: |
| 2666 code.putln( |
| 2667 "%s.%s = *%s;" % ( |
| 2668 type.vtable_cname, |
| 2669 Naming.obj_base_cname, |
| 2670 type.base_type.vtabptr_cname)) |
| 2671 |
| 2672 c_method_entries = [ |
| 2673 entry for entry in type.scope.cfunc_entries |
| 2674 if entry.func_cname ] |
| 2675 if c_method_entries: |
| 2676 for meth_entry in c_method_entries: |
| 2677 cast = meth_entry.type.signature_cast_string() |
| 2678 code.putln( |
| 2679 "%s.%s = %s%s;" % ( |
| 2680 type.vtable_cname, |
| 2681 meth_entry.cname, |
| 2682 cast, |
| 2683 meth_entry.func_cname)) |
| 2684 |
| 2685 def generate_typeptr_assignment_code(self, entry, code): |
| 2686 # Generate code to initialise the typeptr of an extension |
| 2687 # type defined in this module to point to its type object. |
| 2688 type = entry.type |
| 2689 if type.typeobj_cname: |
| 2690 code.putln( |
| 2691 "%s = &%s;" % ( |
| 2692 type.typeptr_cname, type.typeobj_cname)) |
| 2693 |
| 2694 def generate_cfunction_declaration(entry, env, code, definition): |
| 2695 from_cy_utility = entry.used and entry.utility_code_definition |
| 2696 if entry.used and entry.inline_func_in_pxd or (not entry.in_cinclude and (de
finition |
| 2697 or entry.defined_in_pxd or entry.visibility == 'extern' or from_cy_u
tility)): |
| 2698 if entry.visibility == 'extern': |
| 2699 storage_class = Naming.extern_c_macro |
| 2700 dll_linkage = "DL_IMPORT" |
| 2701 elif entry.visibility == 'public': |
| 2702 storage_class = Naming.extern_c_macro |
| 2703 dll_linkage = "DL_EXPORT" |
| 2704 elif entry.visibility == 'private': |
| 2705 storage_class = "static" |
| 2706 dll_linkage = None |
| 2707 else: |
| 2708 storage_class = "static" |
| 2709 dll_linkage = None |
| 2710 type = entry.type |
| 2711 |
| 2712 if entry.defined_in_pxd and not definition: |
| 2713 storage_class = "static" |
| 2714 dll_linkage = None |
| 2715 type = CPtrType(type) |
| 2716 |
| 2717 header = type.declaration_code( |
| 2718 entry.cname, dll_linkage = dll_linkage) |
| 2719 modifiers = code.build_function_modifiers(entry.func_modifiers) |
| 2720 code.putln("%s %s%s; /*proto*/" % ( |
| 2721 storage_class, |
| 2722 modifiers, |
| 2723 header)) |
| 2724 |
| 2725 #-------------------------------------------------------------------------------
----- |
| 2726 # |
| 2727 # Runtime support code |
| 2728 # |
| 2729 #-------------------------------------------------------------------------------
----- |
| 2730 |
| 2731 streq_utility_code = UtilityCode( |
| 2732 proto = """ |
| 2733 static CYTHON_INLINE int __Pyx_StrEq(const char *, const char *); /*proto*/ |
| 2734 """, |
| 2735 impl = """ |
| 2736 static CYTHON_INLINE int __Pyx_StrEq(const char *s1, const char *s2) { |
| 2737 while (*s1 != '\\0' && *s1 == *s2) { s1++; s2++; } |
| 2738 return *s1 == *s2; |
| 2739 } |
| 2740 """) |
| 2741 |
| 2742 #-------------------------------------------------------------------------------
----- |
| 2743 |
| 2744 import_star_utility_code = """ |
| 2745 |
| 2746 /* import_all_from is an unexposed function from ceval.c */ |
| 2747 |
| 2748 static int |
| 2749 __Pyx_import_all_from(PyObject *locals, PyObject *v) |
| 2750 { |
| 2751 PyObject *all = __Pyx_GetAttrString(v, "__all__"); |
| 2752 PyObject *dict, *name, *value; |
| 2753 int skip_leading_underscores = 0; |
| 2754 int pos, err; |
| 2755 |
| 2756 if (all == NULL) { |
| 2757 if (!PyErr_ExceptionMatches(PyExc_AttributeError)) |
| 2758 return -1; /* Unexpected error */ |
| 2759 PyErr_Clear(); |
| 2760 dict = __Pyx_GetAttrString(v, "__dict__"); |
| 2761 if (dict == NULL) { |
| 2762 if (!PyErr_ExceptionMatches(PyExc_AttributeError)) |
| 2763 return -1; |
| 2764 PyErr_SetString(PyExc_ImportError, |
| 2765 "from-import-* object has no __dict__ and no __all__"); |
| 2766 return -1; |
| 2767 } |
| 2768 #if PY_MAJOR_VERSION < 3 |
| 2769 all = PyObject_CallMethod(dict, (char *)"keys", NULL); |
| 2770 #else |
| 2771 all = PyMapping_Keys(dict); |
| 2772 #endif |
| 2773 Py_DECREF(dict); |
| 2774 if (all == NULL) |
| 2775 return -1; |
| 2776 skip_leading_underscores = 1; |
| 2777 } |
| 2778 |
| 2779 for (pos = 0, err = 0; ; pos++) { |
| 2780 name = PySequence_GetItem(all, pos); |
| 2781 if (name == NULL) { |
| 2782 if (!PyErr_ExceptionMatches(PyExc_IndexError)) |
| 2783 err = -1; |
| 2784 else |
| 2785 PyErr_Clear(); |
| 2786 break; |
| 2787 } |
| 2788 if (skip_leading_underscores && |
| 2789 #if PY_MAJOR_VERSION < 3 |
| 2790 PyString_Check(name) && |
| 2791 PyString_AS_STRING(name)[0] == '_') |
| 2792 #else |
| 2793 PyUnicode_Check(name) && |
| 2794 PyUnicode_AS_UNICODE(name)[0] == '_') |
| 2795 #endif |
| 2796 { |
| 2797 Py_DECREF(name); |
| 2798 continue; |
| 2799 } |
| 2800 value = PyObject_GetAttr(v, name); |
| 2801 if (value == NULL) |
| 2802 err = -1; |
| 2803 else if (PyDict_CheckExact(locals)) |
| 2804 err = PyDict_SetItem(locals, name, value); |
| 2805 else |
| 2806 err = PyObject_SetItem(locals, name, value); |
| 2807 Py_DECREF(name); |
| 2808 Py_XDECREF(value); |
| 2809 if (err != 0) |
| 2810 break; |
| 2811 } |
| 2812 Py_DECREF(all); |
| 2813 return err; |
| 2814 } |
| 2815 |
| 2816 |
| 2817 static int %(IMPORT_STAR)s(PyObject* m) { |
| 2818 |
| 2819 int i; |
| 2820 int ret = -1; |
| 2821 char* s; |
| 2822 PyObject *locals = 0; |
| 2823 PyObject *list = 0; |
| 2824 #if PY_MAJOR_VERSION >= 3 |
| 2825 PyObject *utf8_name = 0; |
| 2826 #endif |
| 2827 PyObject *name; |
| 2828 PyObject *item; |
| 2829 |
| 2830 locals = PyDict_New(); if (!locals) goto bad; |
| 2831 if (__Pyx_import_all_from(locals, m) < 0) goto bad; |
| 2832 list = PyDict_Items(locals); if (!list) goto bad; |
| 2833 |
| 2834 for(i=0; i<PyList_GET_SIZE(list); i++) { |
| 2835 name = PyTuple_GET_ITEM(PyList_GET_ITEM(list, i), 0); |
| 2836 item = PyTuple_GET_ITEM(PyList_GET_ITEM(list, i), 1); |
| 2837 #if PY_MAJOR_VERSION >= 3 |
| 2838 utf8_name = PyUnicode_AsUTF8String(name); |
| 2839 if (!utf8_name) goto bad; |
| 2840 s = PyBytes_AS_STRING(utf8_name); |
| 2841 if (%(IMPORT_STAR_SET)s(item, name, s) < 0) goto bad; |
| 2842 Py_DECREF(utf8_name); utf8_name = 0; |
| 2843 #else |
| 2844 s = PyString_AsString(name); |
| 2845 if (!s) goto bad; |
| 2846 if (%(IMPORT_STAR_SET)s(item, name, s) < 0) goto bad; |
| 2847 #endif |
| 2848 } |
| 2849 ret = 0; |
| 2850 |
| 2851 bad: |
| 2852 Py_XDECREF(locals); |
| 2853 Py_XDECREF(list); |
| 2854 #if PY_MAJOR_VERSION >= 3 |
| 2855 Py_XDECREF(utf8_name); |
| 2856 #endif |
| 2857 return ret; |
| 2858 } |
| 2859 """ % {'IMPORT_STAR' : Naming.import_star, |
| 2860 'IMPORT_STAR_SET' : Naming.import_star_set } |
| 2861 |
| 2862 refnanny_utility_code = UtilityCode.load_cached("Refnanny", "ModuleSetupCode.c") |
| 2863 |
| 2864 main_method = UtilityCode.load("MainFunction", "Embed.c") |
| 2865 |
| 2866 packed_struct_utility_code = UtilityCode(proto=""" |
| 2867 #if defined(__GNUC__) |
| 2868 #define __Pyx_PACKED __attribute__((__packed__)) |
| 2869 #else |
| 2870 #define __Pyx_PACKED |
| 2871 #endif |
| 2872 """, impl="", proto_block='utility_code_proto_before_types') |
| 2873 |
| 2874 capsule_utility_code = UtilityCode.load("Capsule") |
OLD | NEW |