Cython has moved to github.

pyrex

view Pyrex/Compiler/ModuleNode.py @ 86:da6e97bb7e6d

Multiple compilation fixed
author Gregory Ewing <greg.ewing@canterbury.ac.nz>
date Sat May 24 15:50:12 2008 +1200 (4 years ago)
parents 12072e0e4fd5
children 43fa19e79098
line source
1 #
2 # Pyrex - Module parse tree node
3 #
5 import os, time
6 from cStringIO import StringIO
7 from PyrexTypes import CPtrType, py_object_type, typecast
8 from Pyrex.Utils import set
10 # Following is set by Testing.py to suppress filename/date comments
11 # in generated files, so as not to produce spurious changes in test
12 # reference files.
14 testing_mode = False
17 import Code
18 import Naming
19 import Nodes
20 import Options
21 import PyrexTypes
22 import TypeSlots
23 import Version
25 from Errors import error
26 from PyrexTypes import py_object_type
27 from Pyrex.Utils import open_new_file, replace_suffix
29 class ModuleNode(Nodes.Node, Nodes.BlockNode):
30 # doc string or None
31 # body StatListNode
32 #
33 # referenced_modules [ModuleScope]
34 # module_temp_cname string
36 def analyse_declarations(self, env):
37 env.doc = self.doc
38 self.body.analyse_declarations(env)
40 def process_implementation(self, env, options, result):
41 self.analyse_declarations(env)
42 env.check_c_classes()
43 self.body.analyse_expressions(env)
44 env.return_type = PyrexTypes.c_void_type
45 self.referenced_modules = self.find_referenced_modules(env)
46 if self.has_imported_c_functions():
47 self.module_temp_cname = env.allocate_temp_pyobject()
48 env.release_temp(self.module_temp_cname)
49 self.generate_dep_file(env, result)
50 self.generate_c_code(env, result)
51 self.generate_h_code(env, options, result)
52 self.generate_api_code(env, result)
54 def has_imported_c_functions(self):
55 for module in self.referenced_modules:
56 for entry in module.cfunc_entries:
57 if entry.defined_in_pxd:
58 return 1
59 return 0
61 def generate_dep_file(self, env, result):
62 modules = self.referenced_modules
63 includes = set(env.pyrex_include_files)
64 for module in modules:
65 for include in module.pyrex_include_files:
66 includes.add(include)
67 if len(modules) > 1 or includes:
68 include_list = list(includes)
69 include_list.sort()
70 dep_file = replace_suffix(result.c_file, ".dep")
71 f = open(dep_file, "w")
72 try:
73 for module in modules[:-1]:
74 f.write("cimport %s\n" % module.qualified_name)
75 for path in include_list:
76 f.write("include %s\n" % path)
77 finally:
78 f.close()
80 def generate_h_code(self, env, options, result):
81 def pub(entries): #, pxd = 0):
82 return [entry for entry in entries
83 if entry.visibility == 'public'] # or pxd and entry.defined_in_pxd]
84 denv = env.definition_scope
85 h_types = pub(denv.type_entries) + pub(env.type_entries)
86 h_vars = pub(denv.var_entries) + pub(env.var_entries)
87 h_funcs = pub(denv.cfunc_entries) + pub(env.cfunc_entries)
88 h_extension_types = pub(denv.c_class_entries) + pub(env.c_class_entries)
89 if h_types or h_vars or h_funcs or h_extension_types:
90 result.h_file = replace_suffix(result.c_file, ".h")
91 h_code = Code.CCodeWriter(open_new_file(result.h_file))
92 if options.generate_pxi:
93 result.i_file = replace_suffix(result.c_file, ".pxi")
94 i_code = Code.PyrexCodeWriter(result.i_file)
95 else:
96 i_code = None
97 guard = Naming.h_guard_prefix + env.qualified_name.replace(".", "__")
98 h_code.put_h_guard(guard)
99 self.generate_extern_c_macro_definition(h_code)
100 self.generate_type_header_code(h_types, h_code)
101 h_code.putln("")
102 h_code.putln("#ifndef %s" % Naming.api_guard_prefix + self.api_name(env))
103 if h_vars:
104 h_code.putln("")
105 for entry in h_vars:
106 self.generate_public_declaration(entry, h_code, i_code)
107 if h_funcs:
108 h_code.putln("")
109 for entry in h_funcs:
110 self.generate_public_declaration(entry, h_code, i_code)
111 if h_extension_types:
112 h_code.putln("")
113 for entry in h_extension_types:
114 self.generate_cclass_header_code(entry.type, h_code)
115 if i_code:
116 self.generate_cclass_include_code(entry.type, i_code)
117 h_code.putln("")
118 h_code.putln("#endif")
119 h_code.putln("")
120 h_code.putln("PyMODINIT_FUNC init%s(void);" % env.module_name)
121 h_code.putln("")
122 h_code.putln("#endif")
124 def generate_public_declaration(self, entry, h_code, i_code):
125 h_code.putln("%s %s;" % (
126 Naming.extern_c_macro,
127 entry.type.declaration_code(
128 entry.cname, dll_linkage = "DL_IMPORT")))
129 if i_code:
130 i_code.putln("cdef extern %s" %
131 entry.type.declaration_code(entry.cname, pyrex = 1))
133 def api_name(self, env):
134 return env.qualified_name.replace(".", "__")
136 def generate_api_code(self, env, result):
137 denv = env.definition_scope
138 api_funcs = []
139 public_extension_types = []
140 has_api_extension_types = 0
141 for entry in denv.cfunc_entries + env.cfunc_entries:
142 if entry.api:
143 api_funcs.append(entry)
144 for entry in denv.c_class_entries + env.c_class_entries:
145 if entry.visibility == 'public':
146 public_extension_types.append(entry)
147 if entry.api:
148 has_api_extension_types = 1
149 if api_funcs or has_api_extension_types:
150 result.api_file = replace_suffix(result.c_file, "_api.h")
151 h_code = Code.CCodeWriter(open_new_file(result.api_file))
152 name = self.api_name(env)
153 guard = Naming.api_guard_prefix + name
154 h_code.put_h_guard(guard)
155 h_code.putln('#include "Python.h"')
156 if result.h_file:
157 h_code.putln('#include "%s"' % os.path.basename(result.h_file))
158 for entry in public_extension_types:
159 type = entry.type
160 h_code.putln("")
161 h_code.putln("static PyTypeObject *%s;" % type.typeptr_cname)
162 h_code.putln("#define %s (*%s)" % (
163 type.typeobj_cname, type.typeptr_cname))
164 if api_funcs:
165 h_code.putln("")
166 for entry in api_funcs:
167 type = CPtrType(entry.type)
168 h_code.putln("static %s;" % type.declaration_code(entry.cname))
169 h_code.putln("")
170 h_code.put_h_guard(Naming.api_func_guard + "import_module")
171 h_code.put(import_module_utility_code[1])
172 h_code.putln("")
173 h_code.putln("#endif")
174 if api_funcs:
175 h_code.putln("")
176 h_code.put(function_import_utility_code[1])
177 if public_extension_types:
178 h_code.putln("")
179 h_code.put(type_import_utility_code[1])
180 h_code.putln("")
181 h_code.putln("static int import_%s(void) {" % name)
182 h_code.putln("PyObject *module = 0;")
183 h_code.putln('module = __Pyx_ImportModule("%s");' % env.qualified_name)
184 h_code.putln("if (!module) goto bad;")
185 for entry in api_funcs:
186 sig = entry.type.signature_string()
187 h_code.putln(
188 'if (__Pyx_ImportFunction(module, "%s", (void**)&%s, "%s") < 0) goto bad;' % (
189 entry.name,
190 entry.cname,
191 sig))
192 h_code.putln("Py_DECREF(module); module = 0;")
193 for entry in public_extension_types:
194 self.generate_type_import_call(entry.type, h_code, "goto bad;")
195 h_code.putln("return 0;")
196 h_code.putln("bad:")
197 h_code.putln("Py_XDECREF(module);")
198 h_code.putln("return -1;")
199 h_code.putln("}")
200 h_code.putln("")
201 h_code.putln("#endif")
203 def generate_cclass_header_code(self, type, h_code):
204 h_code.putln("%s DL_IMPORT(PyTypeObject) %s;" % (
205 Naming.extern_c_macro,
206 type.typeobj_cname))
207 #self.generate_obj_struct_definition(type, h_code)
209 def generate_cclass_include_code(self, type, i_code):
210 i_code.putln("cdef extern class %s.%s:" % (
211 type.module_name, type.name))
212 i_code.indent()
213 var_entries = type.scope.var_entries
214 if var_entries:
215 for entry in var_entries:
216 i_code.putln("cdef %s" %
217 entry.type.declaration_code(entry.cname, pyrex = 1))
218 else:
219 i_code.putln("pass")
220 i_code.dedent()
222 def generate_c_code(self, env, result):
223 code = Code.MainCCodeWriter(StringIO())
224 code.h = Code.CCodeWriter(StringIO())
225 code.init_labels()
227 modules = self.referenced_modules
228 self.generate_module_preamble(env, modules, code.h)
230 code.putln("")
231 code.putln("/* Implementation of %s */" % env.qualified_name)
232 #self.generate_const_definitions(env, code)
233 #self.generate_interned_name_decls(env, code)
234 #self.generate_py_string_decls(env, code)
235 self.body.generate_function_definitions(env, code)
236 #self.generate_interned_name_table(env, code)
237 #self.generate_py_string_table(env, code)
238 self.generate_typeobj_definitions(env, code)
239 self.generate_method_table(env, code)
240 self.generate_filename_init_prototype(code)
241 self.generate_module_init_func(modules[:-1], env, code)
242 self.generate_filename_table(code)
243 self.generate_utility_functions(code)
245 denv = env.definition_scope
246 for module in modules:
247 code.h.putln("")
248 code.h.putln("/* Declarations from %s */" % module.qualified_name)
249 self.generate_declarations_for_module(module, code.h,
250 implementation = module is denv)
252 code.h.putln("")
253 code.h.putln("/* Declarations from implementation of %s */" %
254 env.qualified_name)
255 self.generate_declarations_for_module(env, code.h, implementation = 1)
256 code.global_state.generate_const_declarations(code.h)
257 #self.generate_interned_name_table(code.interned_strings, code.h)
258 #self.generate_py_string_table(code.py_strings, code.h)
259 self.generate_default_value_declarations(env, code.h)
261 f = open_new_file(result.c_file)
262 f.write(code.h.f.getvalue())
263 f.write("\n")
264 f.write(code.f.getvalue())
265 f.close()
266 result.c_file_generated = 1
268 def find_referenced_modules(self, env):
269 # Given the ImplementationScope, find the DefinitionScopes of all
270 # modules cimported, directly or indirectly. Includes this module's
271 # DefinitionScope as the last entry in the list.
272 denv = env.definition_scope
273 module_list = []
274 modules_seen = set()
275 def add_module(module):
276 if module not in modules_seen:
277 modules_seen.add(module)
278 add_modules(module.cimported_modules)
279 module_list.append(module)
280 def add_modules(modules):
281 for module in modules:
282 add_module(module)
283 modules_seen.add(denv)
284 add_modules(denv.cimported_modules)
285 add_modules(env.cimported_modules)
286 module_list.append(denv)
287 #self.print_referenced_modules(module_list) ###
288 return module_list
290 def print_referenced_modules(self, module_list):
291 print "find_referenced_modules: result =",
292 for m in module_list:
293 print m,
294 print
296 def generate_module_preamble(self, env, cimported_modules, code):
297 comment = "Generated by Pyrex"
298 if not testing_mode:
299 comment = "%s %s on %s" % (comment, Version.version, time.asctime())
300 code.putln('/* %s */' % comment)
301 code.putln('')
302 code.putln('#define PY_SSIZE_T_CLEAN')
303 for filename in env.python_include_files:
304 code.putln('#include "%s"' % filename)
305 code.putln("#ifndef PY_LONG_LONG")
306 code.putln(" #define PY_LONG_LONG LONG_LONG")
307 code.putln("#endif")
308 code.putln("#if PY_VERSION_HEX < 0x02050000")
309 code.putln(" typedef int Py_ssize_t;")
310 code.putln(" #define PY_SSIZE_T_MAX INT_MAX")
311 code.putln(" #define PY_SSIZE_T_MIN INT_MIN")
312 code.putln(" #define PyInt_FromSsize_t(z) PyInt_FromLong(z)")
313 code.putln(" #define PyInt_AsSsize_t(o) PyInt_AsLong(o)")
314 code.putln("#endif")
315 code.putln("#ifndef WIN32")
316 code.putln(" #ifndef __stdcall")
317 code.putln(" #define __stdcall")
318 code.putln(" #endif")
319 code.putln(" #ifndef __cdecl")
320 code.putln(" #define __cdecl")
321 code.putln(" #endif")
322 code.putln("#endif")
323 self.generate_extern_c_macro_definition(code)
324 code.putln("#include <math.h>")
325 self.generate_includes(env, cimported_modules, code)
326 code.putln('')
327 code.put(Nodes.utility_function_predeclarations)
328 code.putln('')
329 code.putln('static PyObject *%s;' % env.module_cname)
330 code.putln('static PyObject *%s;' % Naming.builtins_cname)
331 code.putln('static int %s;' % Naming.lineno_cname)
332 code.putln('static char *%s;' % Naming.filename_cname)
333 code.putln('static char **%s;' % Naming.filetable_cname)
334 doc = None
335 doc1 = env.definition_scope.doc
336 doc2 = env.doc
337 if doc1 and doc2:
338 doc = "%s\\n%s" % (doc1, doc2)
339 else:
340 doc = doc1 or doc2
341 if doc:
342 code.putln('')
343 code.putln('static char %s[] = "%s";' % (env.doc_cname, doc))
345 def generate_extern_c_macro_definition(self, code):
346 name = Naming.extern_c_macro
347 code.putln("#ifdef __cplusplus")
348 code.putln('#define %s extern "C"' % name)
349 code.putln("#else")
350 code.putln("#define %s extern" % name)
351 code.putln("#endif")
353 def generate_includes(self, env, cimported_modules, code):
354 includes = env.include_files[:]
355 for module in cimported_modules:
356 for filename in module.include_files:
357 if filename not in includes:
358 includes.append(filename)
359 for filename in includes:
360 code.putln('#include "%s"' % filename)
362 def generate_filename_table(self, code):
363 code.global_state.generate_filename_table(code)
365 def generate_declarations_for_module(self, env, code, implementation):
366 self.generate_type_predeclarations(env, code)
367 self.generate_type_definitions(env, code) #, implementation)
368 self.generate_global_declarations(env, code, implementation)
369 self.generate_cfunction_predeclarations(env, code, implementation)
371 def generate_type_predeclarations(self, env, code):
372 pass
374 def generate_type_header_code(self, type_entries, code):
375 # Generate definitions of structs/unions/enums/typedefs/objstructs.
376 #self.generate_gcc33_hack(env, code) # Is this still needed?
377 #for entry in env.type_entries:
378 for entry in type_entries:
379 if not entry.in_cinclude:
380 #print "generate_type_header_code:", entry.name, repr(entry.type) ###
381 type = entry.type
382 if type.is_typedef: # Must test this first!
383 self.generate_typedef(entry, code)
384 elif type.is_struct_or_union:
385 self.generate_struct_union_definition(entry, code)
386 elif type.is_enum:
387 self.generate_enum_definition(entry, code)
388 elif type.is_extension_type:
389 self.generate_obj_struct_definition(type, code)
391 def generate_type_definitions(self, env, code): #, implementation):
392 #print "generate_type_definitions:", env ###
393 # if definition:
394 # type_entries = env.type_entries
395 # else:
396 # type_entries = []
397 # for entry in env.type_entries:
398 # if entry.defined_in_pxd:
399 # type_entries.append(entry)
400 type_entries = env.type_entries
401 self.generate_type_header_code(type_entries, code)
402 for entry in env.c_class_entries:
403 if not entry.in_cinclude:
404 self.generate_typeobject_predeclaration(entry, code)
405 self.generate_exttype_vtable_struct(entry, code)
406 self.generate_exttype_vtabptr_declaration(entry, code)
408 def generate_gcc33_hack(self, env, code):
409 # Workaround for spurious warning generation in gcc 3.3
410 if 0:
411 code.putln("")
412 for entry in env.c_class_entries:
413 type = entry.type
414 if not type.typedef_flag:
415 name = type.objstruct_cname
416 if name.startswith("__pyx_"):
417 tail = name[6:]
418 else:
419 tail = name
420 code.putln("typedef struct %s __pyx_gcc33_%s;" % (
421 name, tail))
423 def generate_typedef(self, entry, code):
424 base_type = entry.type.typedef_base_type
425 code.putln("")
426 code.putln("typedef %s;" % base_type.declaration_code(entry.cname))
428 def sue_header_footer(self, type, kind, name):
429 if type.typedef_flag:
430 header = "typedef %s {" % kind
431 footer = "} %s;" % name
432 else:
433 header = "%s %s {" % (kind, name)
434 footer = "};"
435 return header, footer
437 def generate_struct_union_definition(self, entry, code):
438 type = entry.type
439 scope = type.scope
440 if scope:
441 header, footer = \
442 self.sue_header_footer(type, type.kind, type.cname)
443 code.putln("")
444 code.putln(header)
445 var_entries = scope.var_entries
446 if not var_entries and not scope.cfunc_entries:
447 error(entry.pos,
448 "Empty struct or union definition not allowed outside a"
449 " 'cdef extern from' block")
450 for attr in var_entries:
451 code.putln(
452 "%s;" %
453 attr.type.declaration_code(attr.cname))
454 code.putln(footer)
456 def generate_enum_definition(self, entry, code):
457 type = entry.type
458 name = entry.cname or entry.name or ""
459 header, footer = \
460 self.sue_header_footer(type, "enum", name)
461 code.putln("")
462 code.putln(header)
463 enum_values = entry.enum_values
464 if not enum_values:
465 error(entry.pos,
466 "Empty enum definition not allowed outside a"
467 " 'cdef extern from' block")
468 else:
469 last_entry = enum_values[-1]
470 for value_entry in enum_values:
471 if value_entry.value == value_entry.name:
472 value_code = value_entry.cname
473 else:
474 value_code = ("%s = %s" % (
475 value_entry.cname,
476 value_entry.value))
477 if value_entry is not last_entry:
478 value_code += ","
479 code.putln(value_code)
480 code.putln(footer)
482 def generate_typeobject_predeclaration(self, entry, code):
483 code.putln("")
484 name = entry.type.typeobj_cname
485 if name:
486 if entry.visibility == 'extern' and not entry.in_cinclude:
487 code.putln("%s DL_IMPORT(PyTypeObject) %s;" % (
488 Naming.extern_c_macro,
489 name))
490 elif entry.visibility == 'public':
491 #code.putln("DL_EXPORT(PyTypeObject) %s;" % name)
492 code.putln("%s DL_EXPORT(PyTypeObject) %s;" % (
493 Naming.extern_c_macro,
494 name))
495 # ??? Do we really need the rest of this? ???
496 #else:
497 # code.putln("staticforward PyTypeObject %s;" % name)
499 def generate_exttype_vtable_struct(self, entry, code):
500 # Generate struct declaration for an extension type's vtable.
501 type = entry.type
502 scope = type.scope
503 if type.vtabstruct_cname:
504 code.putln("")
505 code.putln(
506 "struct %s {" %
507 type.vtabstruct_cname)
508 if type.base_type and type.base_type.vtabstruct_cname:
509 code.putln("struct %s %s;" % (
510 type.base_type.vtabstruct_cname,
511 Naming.obj_base_cname))
512 for method_entry in scope.cfunc_entries:
513 if not method_entry.is_inherited:
514 code.putln(
515 "%s;" % method_entry.type.declaration_code("(*%s)" % method_entry.name))
516 code.putln(
517 "};")
519 def generate_exttype_vtabptr_declaration(self, entry, code):
520 # Generate declaration of pointer to an extension type's vtable.
521 type = entry.type
522 if type.vtabptr_cname:
523 code.putln("static struct %s *%s;" % (
524 type.vtabstruct_cname,
525 type.vtabptr_cname))
527 def generate_obj_struct_definition(self, type, code):
528 # Generate object struct definition for an
529 # extension type.
530 if not type.scope:
531 return # Forward declared but never defined
532 header, footer = \
533 self.sue_header_footer(type, "struct", type.objstruct_cname)
534 code.putln("")
535 code.putln(header)
536 base_type = type.base_type
537 if base_type:
538 code.putln(
539 "%s%s %s;" % (
540 ("struct ", "")[base_type.typedef_flag],
541 base_type.objstruct_cname,
542 Naming.obj_base_cname))
543 else:
544 code.putln(
545 "PyObject_HEAD")
546 if type.vtabslot_cname and not (type.base_type and type.base_type.vtabslot_cname):
547 code.putln(
548 "struct %s *%s;" % (
549 type.vtabstruct_cname,
550 type.vtabslot_cname))
551 for attr in type.scope.var_entries:
552 code.putln(
553 "%s;" %
554 attr.type.declaration_code(attr.cname))
555 code.putln(footer)
557 def generate_global_declarations(self, env, code, implementation):
558 code.putln("")
559 for entry in env.c_class_entries:
560 if implementation or entry.defined_in_pxd:
561 code.putln("static PyTypeObject *%s = 0;" %
562 entry.type.typeptr_cname)
563 #code.putln("/* var_entries */") ###
564 code.put_var_declarations(env.var_entries, static = 1,
565 dll_linkage = "DL_EXPORT", definition = implementation)
567 def generate_default_value_declarations(self, env, code):
568 #code.putln("/* default_entries */") ###
569 code.putln("")
570 code.put_var_declarations(env.default_entries, static = 1)
572 def generate_cfunction_predeclarations(self, env, code, implementation):
573 for entry in env.cfunc_entries:
574 if not entry.in_cinclude:
575 # and (definition or entry.defined_in_pxd or
576 # entry.visibility == 'extern'):
577 if entry.visibility in ('public', 'extern'):
578 dll_linkage = "DL_EXPORT"
579 else:
580 dll_linkage = None
581 type = entry.type
582 if not implementation: #and entry.defined_in_pxd:
583 type = CPtrType(type)
584 header = type.declaration_code(entry.cname,
585 dll_linkage = dll_linkage)
586 if entry.visibility <> 'private':
587 storage_class = "%s " % Naming.extern_c_macro
588 else:
589 storage_class = "static "
590 code.putln("%s%s; /*proto*/" % (
591 storage_class,
592 header))
594 def generate_typeobj_definitions(self, env, code):
595 full_module_name = env.qualified_name
596 denv = env.definition_scope
597 for entry in denv.c_class_entries + env.c_class_entries:
598 #print "generate_typeobj_definitions:", entry.name
599 #print "...visibility =", entry.visibility
600 if entry.visibility <> 'extern':
601 type = entry.type
602 scope = type.scope
603 if scope: # could be None if there was an error
604 self.generate_exttype_vtable(scope, code)
605 self.generate_new_function(scope, code)
606 self.generate_dealloc_function(scope, code)
607 self.generate_traverse_function(scope, code)
608 self.generate_clear_function(scope, code)
609 if scope.defines_any(["__getitem__"]):
610 self.generate_getitem_int_function(scope, code)
611 if scope.defines_any(["__setitem__", "__delitem__"]):
612 self.generate_ass_subscript_function(scope, code)
613 if scope.defines_any(["__setslice__", "__delslice__"]):
614 self.generate_ass_slice_function(scope, code)
615 if scope.defines_any(["__getattr__"]):
616 self.generate_getattro_function(scope, code)
617 if scope.defines_any(["__setattr__", "__delattr__"]):
618 self.generate_setattro_function(scope, code)
619 if scope.defines_any(["__get__"]):
620 self.generate_descr_get_function(scope, code)
621 if scope.defines_any(["__set__", "__delete__"]):
622 self.generate_descr_set_function(scope, code)
623 self.generate_property_accessors(scope, code)
624 self.generate_method_table(scope, code)
625 self.generate_member_table(scope, code)
626 self.generate_getset_table(scope, code)
627 self.generate_typeobj_definition(full_module_name, entry, code)
629 def generate_exttype_vtable(self, scope, code):
630 # Generate the definition of an extension type's vtable.
631 type = scope.parent_type
632 if type.vtable_cname:
633 code.putln("static struct %s %s;" % (
634 type.vtabstruct_cname,
635 type.vtable_cname))
637 def generate_self_cast(self, scope, code):
638 type = scope.parent_type
639 code.putln(
640 "%s = (%s)o;" % (
641 type.declaration_code("p"),
642 type.declaration_code("")))
644 def generate_new_function(self, scope, code):
645 type = scope.parent_type
646 base_type = type.base_type
647 py_attrs = []
648 for entry in scope.var_entries:
649 if entry.type.is_pyobject:
650 py_attrs.append(entry)
651 need_self_cast = type.vtabslot_cname or py_attrs
652 code.putln("")
653 code.putln(
654 "static PyObject *%s(PyTypeObject *t, PyObject *a, PyObject *k) {"
655 % scope.mangle_internal("tp_new"))
656 if need_self_cast:
657 code.putln(
658 "%s;"
659 % scope.parent_type.declaration_code("p"))
660 if base_type:
661 code.putln(
662 "PyObject *o = %s->tp_new(t, a, k);" %
663 base_type.typeptr_cname)
664 else:
665 code.putln(
666 "PyObject *o = (*t->tp_alloc)(t, 0);")
667 code.putln(
668 "if (!o) return 0;")
669 if need_self_cast:
670 code.putln(
671 "p = %s;"
672 % type.cast_code("o"))
673 #if need_self_cast:
674 # self.generate_self_cast(scope, code)
675 if type.vtabslot_cname:
676 code.putln("*(struct %s **)&p->%s = %s;" % (
677 type.vtabstruct_cname,
678 type.vtabslot_cname,
679 type.vtabptr_cname))
680 for entry in py_attrs:
681 if entry.name == "__weakref__":
682 code.putln("p->%s = 0;" % entry.cname)
683 else:
684 code.put_init_var_to_py_none(entry, "p->%s")
685 entry = scope.lookup_here("__new__")
686 if entry:
687 code.putln(
688 "if (%s(o, a, k) < 0) {" %
689 entry.func_cname)
690 code.put_decref_clear("o", py_object_type);
691 code.putln(
692 "}")
693 code.putln(
694 "return o;")
695 code.putln(
696 "}")
698 def generate_dealloc_function(self, scope, code):
699 base_type = scope.parent_type.base_type
700 code.putln("")
701 code.putln(
702 "static void %s(PyObject *o) {"
703 % scope.mangle_internal("tp_dealloc"))
704 #py_attrs = []
705 #for entry in scope.var_entries:
706 # if entry.type.is_pyobject and entry.name <> "__weakref__":
707 # py_attrs.append(entry)
708 py_attrs = scope.pyattr_entries
709 if py_attrs:
710 self.generate_self_cast(scope, code)
711 self.generate_usr_dealloc_call(scope, code)
712 if scope.lookup_here("__weakref__"):
713 code.putln("PyObject_ClearWeakRefs(o);")
714 for entry in py_attrs:
715 code.put_xdecref("p->%s" % entry.cname, entry.type)
716 if base_type:
717 code.putln(
718 "%s->tp_dealloc(o);" %
719 base_type.typeptr_cname)
720 else:
721 code.putln(
722 "(*o->ob_type->tp_free)(o);")
723 code.putln(
724 "}")
726 def generate_usr_dealloc_call(self, scope, code):
727 entry = scope.lookup_here("__dealloc__")
728 if entry:
729 code.putln(
730 "{")
731 code.putln(
732 "PyObject *etype, *eval, *etb;")
733 code.putln(
734 "PyErr_Fetch(&etype, &eval, &etb);")
735 code.putln(
736 "++o->ob_refcnt;")
737 code.putln(
738 "%s(o);" %
739 entry.func_cname)
740 code.putln(
741 "if (PyErr_Occurred()) PyErr_WriteUnraisable(o);")
742 code.putln(
743 "--o->ob_refcnt;")
744 code.putln(
745 "PyErr_Restore(etype, eval, etb);")
746 code.putln(
747 "}")
749 def generate_traverse_function(self, scope, code):
750 py_attrs = scope.pyattr_entries
751 if py_attrs:
752 base_type = scope.parent_type.base_type
753 code.putln("")
754 code.putln(
755 "static int %s(PyObject *o, visitproc v, void *a) {"
756 % scope.mangle_internal("tp_traverse"))
757 code.putln(
758 "int e;")
759 self.generate_self_cast(scope, code)
760 if base_type:
761 code.putln(
762 "traverseproc t;")
763 code.putln(
764 "if ((t = %s->tp_traverse)) {" %
765 base_type.typeptr_cname)
766 code.putln(
767 "e = t(o, v, a); if (e) return e;")
768 code.putln(
769 "}")
770 for entry in py_attrs:
771 var_code = "p->%s" % entry.cname
772 code.putln(
773 "if (%s) {"
774 % var_code)
775 if entry.type.is_extension_type:
776 var_code = "((PyObject*)%s)" % var_code
777 code.putln(
778 "e = (*v)(%s, a); if (e) return e;"
779 % var_code)
780 code.putln(
781 "}")
782 code.putln(
783 "return 0;")
784 code.putln(
785 "}")
787 def generate_clear_function(self, scope, code):
788 py_attrs = scope.pyattr_entries
789 if py_attrs:
790 base_type = scope.parent_type.base_type
791 code.putln("")
792 code.putln(
793 "static int %s(PyObject *o) {"
794 % scope.mangle_internal("tp_clear"))
795 self.generate_self_cast(scope, code)
796 code.putln(
797 "PyObject *t;")
798 if base_type:
799 code.putln(
800 "inquiry c;")
801 code.putln(
802 "if ((c = %s->tp_clear)) {" %
803 base_type.typeptr_cname)
804 code.putln(
805 "c(o);")
806 code.putln(
807 "}")
808 for entry in py_attrs:
809 name = "p->%s" % entry.cname
810 code.putln(
811 "t = %s; " %
812 typecast(py_object_type, entry.type, name))
813 code.put_init_var_to_py_none(entry, "p->%s")
814 #code.put_xdecref(name, entry.type)
815 code.putln(
816 "Py_XDECREF(t);")
817 code.putln(
818 "return 0;")
819 code.putln(
820 "}")
822 def generate_getitem_int_function(self, scope, code):
823 # This function is put into the sq_item slot when
824 # a __getitem__ method is present. It converts its
825 # argument to a Python integer and calls mp_subscript.
826 code.putln(
827 "static PyObject *%s(PyObject *o, Py_ssize_t i) {" %
828 scope.mangle_internal("sq_item"))
829 code.putln(
830 "PyObject *r;")
831 code.putln(
832 "PyObject *x = PyInt_FromSsize_t(i); if(!x) return 0;")
833 code.putln(
834 "r = o->ob_type->tp_as_mapping->mp_subscript(o, x);")
835 code.putln(
836 "Py_DECREF(x);")
837 code.putln(
838 "return r;")
839 code.putln(
840 "}")
842 def generate_ass_subscript_function(self, scope, code):
843 # Setting and deleting an item are both done through
844 # the ass_subscript method, so we dispatch to user's __setitem__
845 # or __delitem__, or raise an exception.
846 base_type = scope.parent_type.base_type
847 set_entry = scope.lookup_here("__setitem__")
848 del_entry = scope.lookup_here("__delitem__")
849 code.putln("")
850 code.putln(
851 "static int %s(PyObject *o, PyObject *i, PyObject *v) {" %
852 scope.mangle_internal("mp_ass_subscript"))
853 code.putln(
854 "if (v) {")
855 if set_entry:
856 code.putln(
857 "return %s(o, i, v);" %
858 set_entry.func_cname)
859 else:
860 self.generate_guarded_basetype_call(
861 base_type, "tp_as_mapping", "mp_ass_subscript", "o, i, v", code)
862 code.putln(
863 "PyErr_Format(PyExc_NotImplementedError,")
864 code.putln(
865 ' "Subscript assignment not supported by %s", o->ob_type->tp_name);')
866 code.putln(
867 "return -1;")
868 code.putln(
869 "}")
870 code.putln(
871 "else {")
872 if del_entry:
873 code.putln(
874 "return %s(o, i);" %
875 del_entry.func_cname)
876 else:
877 self.generate_guarded_basetype_call(
878 base_type, "tp_as_mapping", "mp_ass_subscript", "o, i, v", code)
879 code.putln(
880 "PyErr_Format(PyExc_NotImplementedError,")
881 code.putln(
882 ' "Subscript deletion not supported by %s", o->ob_type->tp_name);')
883 code.putln(
884 "return -1;")
885 code.putln(
886 "}")
887 code.putln(
888 "}")
890 def generate_guarded_basetype_call(
891 self, base_type, substructure, slot, args, code):
892 if base_type:
893 base_tpname = base_type.typeptr_cname
894 if substructure:
895 code.putln(
896 "if (%s->%s && %s->%s->%s)" % (
897 base_tpname, substructure, base_tpname, substructure, slot))
898 code.putln(
899 " return %s->%s->%s(%s);" % (
900 base_tpname, substructure, slot, args))
901 else:
902 code.putln(
903 "if (%s->%s)" % (
904 base_tpname, slot))
905 code.putln(
906 " return %s->%s(%s);" % (
907 base_tpname, slot, args))
909 def generate_ass_slice_function(self, scope, code):
910 # Setting and deleting a slice are both done through
911 # the ass_slice method, so we dispatch to user's __setslice__
912 # or __delslice__, or raise an exception.
913 base_type = scope.parent_type.base_type
914 set_entry = scope.lookup_here("__setslice__")
915 del_entry = scope.lookup_here("__delslice__")
916 code.putln("")
917 code.putln(
918 "static int %s(PyObject *o, Py_ssize_t i, Py_ssize_t j, PyObject *v) {" %
919 scope.mangle_internal("sq_ass_slice"))
920 code.putln(
921 "if (v) {")
922 if set_entry:
923 code.putln(
924 "return %s(o, i, j, v);" %
925 set_entry.func_cname)
926 else:
927 self.generate_guarded_basetype_call(
928 base_type, "tp_as_sequence", "sq_ass_slice", "o, i, j, v", code)
929 code.putln(
930 "PyErr_Format(PyExc_NotImplementedError,")
931 code.putln(
932 ' "2-element slice assignment not supported by %s", o->ob_type->tp_name);')
933 code.putln(
934 "return -1;")
935 code.putln(
936 "}")
937 code.putln(
938 "else {")
939 if del_entry:
940 code.putln(
941 "return %s(o, i, j);" %
942 del_entry.func_cname)
943 else:
944 self.generate_guarded_basetype_call(
945 base_type, "tp_as_sequence", "sq_ass_slice", "o, i, j, v", code)
946 code.putln(
947 "PyErr_Format(PyExc_NotImplementedError,")
948 code.putln(
949 ' "2-element slice deletion not supported by %s", o->ob_type->tp_name);')
950 code.putln(
951 "return -1;")
952 code.putln(
953 "}")
954 code.putln(
955 "}")
957 def generate_getattro_function(self, scope, code):
958 # First try to get the attribute using PyObject_GenericGetAttr.
959 # If that raises an AttributeError, call the user's __getattr__
960 # method.
961 entry = scope.lookup_here("__getattr__")
962 code.putln("")
963 code.putln(
964 "static PyObject *%s(PyObject *o, PyObject *n) {"
965 % scope.mangle_internal("tp_getattro"))
966 code.putln(
967 "PyObject *v = PyObject_GenericGetAttr(o, n);")
968 code.putln(
969 "if (!v && PyErr_ExceptionMatches(PyExc_AttributeError)) {")
970 code.putln(
971 "PyErr_Clear();")
972 code.putln(
973 "v = %s(o, n);" %
974 entry.func_cname)
975 code.putln(
976 "}")
977 code.putln(
978 "return v;")
979 code.putln(
980 "}")
982 def generate_setattro_function(self, scope, code):
983 # Setting and deleting an attribute are both done through
984 # the setattro method, so we dispatch to user's __setattr__
985 # or __delattr__ or fall back on PyObject_GenericSetAttr.
986 base_type = scope.parent_type.base_type
987 set_entry = scope.lookup_here("__setattr__")
988 del_entry = scope.lookup_here("__delattr__")
989 code.putln("")
990 code.putln(
991 "static int %s(PyObject *o, PyObject *n, PyObject *v) {" %
992 scope.mangle_internal("tp_setattro"))
993 code.putln(
994 "if (v) {")
995 if set_entry:
996 code.putln(
997 "return %s(o, n, v);" %
998 set_entry.func_cname)
999 else:
1000 self.generate_guarded_basetype_call(
1001 base_type, None, "tp_setattro", "o, n, v", code)
1002 code.putln(
1003 "return PyObject_GenericSetAttr(o, n, v);")
1004 code.putln(
1005 "}")
1006 code.putln(
1007 "else {")
1008 if del_entry:
1009 code.putln(
1010 "return %s(o, n);" %
1011 del_entry.func_cname)
1012 else:
1013 self.generate_guarded_basetype_call(
1014 base_type, None, "tp_setattro", "o, n, v", code)
1015 code.putln(
1016 "return PyObject_GenericSetAttr(o, n, 0);")
1017 code.putln(
1018 "}")
1019 code.putln(
1020 "}")
1022 def generate_descr_get_function(self, scope, code):
1023 # The __get__ function of a descriptor object can be
1024 # called with NULL for the second or third arguments
1025 # under some circumstances, so we replace them with
1026 # None in that case.
1027 user_get_entry = scope.lookup_here("__get__")
1028 code.putln("")
1029 code.putln(
1030 "static PyObject *%s(PyObject *o, PyObject *i, PyObject *c) {" %
1031 scope.mangle_internal("tp_descr_get"))
1032 code.putln(
1033 "PyObject *r = 0;")
1034 code.putln(
1035 "if (!i) i = Py_None;")
1036 code.putln(
1037 "if (!c) c = Py_None;")
1038 #code.put_incref("i", py_object_type)
1039 #code.put_incref("c", py_object_type)
1040 code.putln(
1041 "r = %s(o, i, c);" %
1042 user_get_entry.func_cname)
1043 #code.put_decref("i", py_object_type)
1044 #code.put_decref("c", py_object_type)
1045 code.putln(
1046 "return r;")
1047 code.putln(
1048 "}")
1050 def generate_descr_set_function(self, scope, code):
1051 # Setting and deleting are both done through the __set__
1052 # method of a descriptor, so we dispatch to user's __set__
1053 # or __delete__ or raise an exception.
1054 base_type = scope.parent_type.base_type
1055 user_set_entry = scope.lookup_here("__set__")
1056 user_del_entry = scope.lookup_here("__delete__")
1057 code.putln("")
1058 code.putln(
1059 "static int %s(PyObject *o, PyObject *i, PyObject *v) {" %
1060 scope.mangle_internal("tp_descr_set"))
1061 code.putln(
1062 "if (v) {")
1063 if user_set_entry:
1064 code.putln(
1065 "return %s(o, i, v);" %
1066 user_set_entry.func_cname)
1067 else:
1068 self.generate_guarded_basetype_call(
1069 base_type, None, "tp_descr_set", "o, i, v", code)
1070 code.putln(
1071 'PyErr_SetString(PyExc_NotImplementedError, "__set__");')
1072 code.putln(
1073 "return -1;")
1074 code.putln(
1075 "}")
1076 code.putln(
1077 "else {")
1078 if user_del_entry:
1079 code.putln(
1080 "return %s(o, i);" %
1081 user_del_entry.func_cname)
1082 else:
1083 self.generate_guarded_basetype_call(
1084 base_type, None, "tp_descr_set", "o, i, v", code)
1085 code.putln(
1086 'PyErr_SetString(PyExc_NotImplementedError, "__delete__");')
1087 code.putln(
1088 "return -1;")
1089 code.putln(
1090 "}")
1091 code.putln(
1092 "}")
1094 def generate_property_accessors(self, cclass_scope, code):
1095 for entry in cclass_scope.property_entries:
1096 property_scope = entry.scope
1097 if property_scope.defines_any(["__get__"]):
1098 self.generate_property_get_function(entry, code)
1099 if property_scope.defines_any(["__set__", "__del__"]):
1100 self.generate_property_set_function(entry, code)
1102 def generate_property_get_function(self, property_entry, code):
1103 property_scope = property_entry.scope
1104 property_entry.getter_cname = property_scope.parent_scope.mangle(
1105 Naming.prop_get_prefix, property_entry.name)
1106 get_entry = property_scope.lookup_here("__get__")
1107 code.putln("")
1108 code.putln(
1109 "static PyObject *%s(PyObject *o, void *x) {" %
1110 property_entry.getter_cname)
1111 code.putln(
1112 "return %s(o);" %
1113 get_entry.func_cname)
1114 code.putln(
1115 "}")
1117 def generate_property_set_function(self, property_entry, code):
1118 property_scope = property_entry.scope
1119 property_entry.setter_cname = property_scope.parent_scope.mangle(
1120 Naming.prop_set_prefix, property_entry.name)
1121 set_entry = property_scope.lookup_here("__set__")
1122 del_entry = property_scope.lookup_here("__del__")
1123 code.putln("")
1124 code.putln(
1125 "static int %s(PyObject *o, PyObject *v, void *x) {" %
1126 property_entry.setter_cname)
1127 code.putln(
1128 "if (v) {")
1129 if set_entry:
1130 code.putln(
1131 "return %s(o, v);" %
1132 set_entry.func_cname)
1133 else:
1134 code.putln(
1135 'PyErr_SetString(PyExc_NotImplementedError, "__set__");')
1136 code.putln(
1137 "return -1;")
1138 code.putln(
1139 "}")
1140 code.putln(
1141 "else {")
1142 if del_entry:
1143 code.putln(
1144 "return %s(o);" %
1145 del_entry.func_cname)
1146 else:
1147 code.putln(
1148 'PyErr_SetString(PyExc_NotImplementedError, "__del__");')
1149 code.putln(
1150 "return -1;")
1151 code.putln(
1152 "}")
1153 code.putln(
1154 "}")
1156 def generate_typeobj_definition(self, modname, entry, code):
1157 type = entry.type
1158 scope = type.scope
1159 for suite in TypeSlots.substructures:
1160 suite.generate_substructure(scope, code)
1161 code.putln("")
1162 if entry.visibility == 'public':
1163 header = "DL_EXPORT(PyTypeObject) %s = {"
1164 else:
1165 header = "PyTypeObject %s = {"
1166 code.putln(header % type.typeobj_cname)
1167 code.putln(
1168 "PyObject_HEAD_INIT(0)")
1169 code.putln(
1170 "0, /*ob_size*/")
1171 code.putln(
1172 '"%s.%s", /*tp_name*/' % (
1173 modname, scope.class_name))
1174 if type.typedef_flag:
1175 objstruct = type.objstruct_cname
1176 else:
1177 #objstruct = "struct %s" % scope.parent_type.objstruct_cname
1178 objstruct = "struct %s" % type.objstruct_cname
1179 code.putln(
1180 "sizeof(%s), /*tp_basicsize*/" %
1181 objstruct)
1182 code.putln(
1183 "0, /*tp_itemsize*/")
1184 for slot in TypeSlots.slot_table:
1185 slot.generate(scope, code)
1186 code.putln(
1187 "};")
1189 def generate_method_table(self, env, code):
1190 code.putln("")
1191 code.putln(
1192 "static struct PyMethodDef %s[] = {" %
1193 env.method_table_cname)
1194 for entry in env.pyfunc_entries:
1195 code.put_pymethoddef(entry, ",")
1196 code.putln(
1197 "{0, 0, 0, 0}")
1198 code.putln(
1199 "};")
1201 def generate_member_table(self, env, code):
1202 #print "ModuleNode.generate_member_table: scope =", env ###
1203 if env.public_attr_entries:
1204 code.putln("")
1205 code.putln(
1206 "static struct PyMemberDef %s[] = {" %
1207 env.member_table_cname)
1208 type = env.parent_type
1209 if type.typedef_flag:
1210 objstruct = type.objstruct_cname
1211 else:
1212 objstruct = "struct %s" % type.objstruct_cname
1213 for entry in env.public_attr_entries:
1214 type_code = entry.type.pymemberdef_typecode
1215 if entry.visibility == 'readonly':
1216 flags = "READONLY"
1217 else:
1218 flags = "0"
1219 code.putln('{"%s", %s, %s, %s, 0},' % (
1220 entry.name,
1221 type_code,
1222 "offsetof(%s, %s)" % (objstruct, entry.name),
1223 flags))
1224 code.putln(
1225 "{0, 0, 0, 0, 0}")
1226 code.putln(
1227 "};")
1229 def generate_getset_table(self, env, code):
1230 if env.property_entries:
1231 code.putln("")
1232 code.putln(
1233 "static struct PyGetSetDef %s[] = {" %
1234 env.getset_table_cname)
1235 for entry in env.property_entries:
1236 if entry.doc:
1237 doc_code = code.get_string_const(entry.doc)
1238 else:
1239 doc_code = "0"
1240 code.putln(
1241 '{"%s", %s, %s, %s, 0},' % (
1242 entry.name,
1243 entry.getter_cname or "0",
1244 entry.setter_cname or "0",
1245 doc_code))
1246 code.putln(
1247 "{0, 0, 0, 0, 0}")
1248 code.putln(
1249 "};")
1251 # def generate_interned_name_table(self, env, code):
1252 # items = env.intern_map.items()
1253 # if items:
1254 # items.sort()
1255 # code.putln("")
1256 # code.putln(
1257 # "static __Pyx_InternTabEntry %s[] = {" %
1258 # Naming.intern_tab_cname)
1259 # for (name, cname) in items:
1260 # code.putln(
1261 # '{&%s, "%s"},' % (
1262 # cname,
1263 # name))
1264 # code.putln(
1265 # "{0, 0}")
1266 # code.putln(
1267 # "};")
1269 # def generate_py_string_table(self, env, code):
1270 # entries = env.all_pystring_entries
1271 # if entries:
1272 # code.putln("")
1273 # code.putln(
1274 # "static __Pyx_StringTabEntry %s[] = {" %
1275 # Naming.stringtab_cname)
1276 # for entry in entries:
1277 # code.putln(
1278 # "{&%s, %s, sizeof(%s)}," % (
1279 # entry.pystring_cname,
1280 # entry.cname,
1281 # entry.cname))
1282 # code.putln(
1283 # "{0, 0, 0}")
1284 # code.putln(
1285 # "};")
1287 def generate_interned_name_table(self, interned_strings, code):
1288 code.putln("")
1289 code.putln(
1290 "static PyObject **%s[] = {" % Naming.intern_tab_cname)
1291 for s in interned_strings:
1292 code.putln("&%s," % s.py_cname)
1293 code.putln("0")
1294 code.putln(
1295 "};")
1297 # def generate_py_string_table(self, py_strings, code):
1298 # interned = []
1299 # uninterned = []
1300 # for s in py_strings:
1301 # if s.is_interned:
1302 # interned.append(s)
1303 # else:
1304 # uninterned.append(s)
1305 # code.putln("")
1306 # code.putln(
1307 # "static __Pyx_StringTabEntry %s[] = {" %
1308 # Naming.stringtab_cname)
1309 # for s in interned + uninterned:
1310 # cname = s.cname
1311 # code.putln(
1312 # "{&%s, %s, sizeof(%s)}," % (
1313 # s.py_cname,
1314 # cname,
1315 # cname))
1316 # code.putln(
1317 # "{0, 0, 0}")
1318 # code.putln(
1319 # "};")
1321 def generate_filename_init_prototype(self, code):
1322 code.putln("");
1323 code.putln("static void %s(void); /*proto*/" % Naming.fileinit_cname)
1325 def generate_module_init_func(self, imported_modules, env, code):
1326 denv = env.definition_scope
1327 code.putln("")
1328 header = "PyMODINIT_FUNC init%s(void)" % env.module_name
1329 code.putln("%s; /*proto*/" % header)
1330 code.putln("%s {" % header)
1331 code.put_var_declarations(env.temp_entries)
1333 #code.putln("/*--- Libary function declarations ---*/")
1334 env.generate_library_function_declarations(code)
1335 self.generate_filename_init_call(code)
1337 #code.putln("/*--- Module creation code ---*/")
1338 self.generate_module_creation_code(env, code)
1340 #code.putln("/*--- String init code ---*/")
1341 self.generate_string_init_code(env, code)
1343 #code.putln("/*--- Intern code ---*/")
1344 #self.generate_intern_code(env, code)
1346 #code.putln("/*--- Global init code ---*/")
1347 self.generate_global_init_code(env, code)
1349 #code.putln("/*--- Function export code ---*/")
1350 self.generate_pxd_function_export_code(env, code)
1351 self.generate_api_function_export_code(env, code)
1353 #code.putln("/*--- Function import code ---*/")
1354 for module in imported_modules:
1355 self.generate_c_function_import_code_for_module(module, env, code)
1357 #code.putln("/*--- Type init code ---*/")
1358 self.generate_type_init_code(env, code)
1360 #code.putln("/*--- Type import code ---*/")
1361 for module in imported_modules:
1362 self.generate_type_import_code_for_module(module, env, code)
1364 #code.putln("/*--- Execution code ---*/")
1365 self.body.generate_execution_code(code)
1366 code.putln("return;")
1367 code.put_label(code.error_label)
1368 code.put_var_xdecrefs(env.temp_entries)
1369 code.putln('__Pyx_AddTraceback("%s");' % (env.qualified_name))
1370 code.use_utility_code(Nodes.traceback_utility_code)
1371 code.putln('}')
1373 def generate_filename_init_call(self, code):
1374 code.putln("%s();" % Naming.fileinit_cname)
1376 def generate_module_creation_code(self, env, code):
1377 # Generate code to create the module object and
1378 # install the builtins.
1379 if env.doc:
1380 doc = env.doc_cname
1381 else:
1382 doc = "0"
1383 code.putln(
1384 '%s = Py_InitModule4("%s", %s, %s, 0, PYTHON_API_VERSION);' % (
1385 env.module_cname,
1386 env.module_name,
1387 env.method_table_cname,
1388 doc))
1389 code.putln(
1390 "if (!%s) %s;" % (
1391 env.module_cname,
1392 code.error_goto(self.pos)));
1393 code.putln(
1394 "Py_INCREF(%s);" %
1395 env.module_cname)
1396 code.putln(
1397 '%s = PyImport_AddModule("__builtin__");' %
1398 Naming.builtins_cname)
1399 code.putln(
1400 "if (!%s) %s;" % (
1401 Naming.builtins_cname,
1402 code.error_goto(self.pos)));
1403 code.putln(
1404 'if (PyObject_SetAttrString(%s, "__builtins__", %s) < 0) %s;' % (
1405 env.module_cname,
1406 Naming.builtins_cname,
1407 code.error_goto(self.pos)))
1409 # def generate_intern_code(self, env, code):
1410 # code.use_utility_code(Nodes.init_intern_tab_utility_code);
1411 # code.putln(
1412 # "if (__Pyx_InternStrings(%s) < 0) %s;" % (
1413 # Naming.intern_tab_cname,
1414 # code.error_goto(self.pos)))
1416 def generate_string_init_code(self, env, code):
1417 code.use_utility_code(Nodes.init_string_tab_utility_code)
1418 code.putln(
1419 "if (__Pyx_InitStrings(%s) < 0) %s;" % (
1420 Naming.stringtab_cname,
1421 code.error_goto(self.pos)))
1423 def generate_global_init_code(self, env, code):
1424 # Generate code to initialise global PyObject *
1425 # variables to None.
1426 for entry in env.var_entries:
1427 if entry.visibility <> 'extern':
1428 if entry.type.is_pyobject:
1429 code.put_init_var_to_py_none(entry)
1431 def generate_pxd_function_export_code(self, env, code):
1432 denv = env.definition_scope
1433 for entry in denv.cfunc_entries:
1434 self.generate_c_function_export_code(env, entry, code)
1436 def generate_api_function_export_code(self, env, code):
1437 for entry in env.cfunc_entries:
1438 if entry.api:
1439 self.generate_c_function_export_code(env, entry, code)
1441 # def generate_c_function_export_code(self, env, code):
1442 # # Generate code to create PyCFunction wrappers for exported C functions.
1443 # for entry in env.cfunc_entries:
1444 # if entry.api or entry.defined_in_pxd:
1446 def generate_c_function_export_code(self, env, entry, code):
1447 code.use_utility_code(function_export_utility_code)
1448 signature = entry.type.signature_string()
1449 code.putln('if (__Pyx_ExportFunction("%s", (void*)%s, "%s") < 0) %s' % (
1450 entry.name,
1451 entry.cname,
1452 signature,
1453 code.error_goto(self.pos)))
1455 def generate_type_import_code_for_module(self, module, env, code):
1456 # Generate type import code for all exported extension types in
1457 # an imported module.
1458 #if module.c_class_entries:
1459 #print "generate_type_import_code_for_module:", module ###
1460 for entry in module.c_class_entries:
1461 if entry.defined_in_pxd:
1462 self.generate_type_import_code(env, entry.type, entry.pos, code)
1464 def generate_c_function_import_code_for_module(self, module, env, code):
1465 # Generate import code for all exported C functions in a cimported module.
1466 entries = []
1467 for entry in module.cfunc_entries:
1468 if entry.defined_in_pxd:
1469 entries.append(entry)
1470 if entries:
1471 code.use_utility_code(import_module_utility_code)
1472 code.use_utility_code(function_import_utility_code)
1473 temp = self.module_temp_cname
1474 code.putln(
1475 '%s = __Pyx_ImportModule("%s"); if (!%s) %s' % (
1476 temp,
1477 module.qualified_name,
1478 temp,
1479 code.error_goto(self.pos)))
1480 for entry in entries:
1481 code.putln(
1482 'if (__Pyx_ImportFunction(%s, "%s", (void**)&%s, "%s") < 0) %s' % (
1483 temp,
1484 entry.name,
1485 entry.cname,
1486 entry.type.signature_string(),
1487 code.error_goto(self.pos)))
1488 code.putln("Py_DECREF(%s); %s = 0;" % (temp, temp))
1490 def generate_type_init_code(self, env, code):
1491 # Generate type import code for extern extension types
1492 # and type ready code for non-extern ones.
1493 #print "generate_type_init_code:", env ###
1494 denv = env.definition_scope
1495 for entry in denv.c_class_entries + env.c_class_entries:
1496 if entry.visibility == 'extern':
1497 self.generate_type_import_code(env, entry.type, entry.pos, code)
1498 else:
1499 self.generate_base_type_import_code(env, entry, code)
1500 self.generate_exttype_vtable_init_code(entry, code)
1501 self.generate_type_ready_code(env, entry, code)
1502 self.generate_typeptr_assignment_code(entry, code)
1504 def generate_base_type_import_code(self, env, entry, code):
1505 base_type = entry.type.base_type
1506 if base_type and base_type.module_name <> env.qualified_name:
1507 self.generate_type_import_code(env, base_type, self.pos, code)
1509 def use_type_import_utility_code(self, code):
1510 import ExprNodes
1511 code.use_utility_code(type_import_utility_code)
1512 code.use_utility_code(import_module_utility_code)
1514 def generate_type_import_code(self, env, type, pos, code):
1515 # If not already done, generate code to import the typeobject of an
1516 # extension type defined in another module, and extract its C method
1517 # table pointer if any.
1518 #print "generate_type_import_code:", type ###
1519 if type in env.types_imported:
1520 return
1521 if type.typedef_flag:
1522 objstruct = type.objstruct_cname
1523 else:
1524 objstruct = "struct %s" % type.objstruct_cname
1525 self.generate_type_import_call(type, code, code.error_goto(pos))
1526 self.use_type_import_utility_code(code)
1527 if type.vtabptr_cname:
1528 code.putln(
1529 "if (__Pyx_GetVtable(%s->tp_dict, &%s) < 0) %s" % (
1530 type.typeptr_cname,
1531 type.vtabptr_cname,
1532 code.error_goto(pos)))
1533 code.use_utility_code(Nodes.get_vtable_utility_code)
1534 env.types_imported[type] = 1
1536 def generate_type_import_call(self, type, code, error_code):
1537 if type.typedef_flag:
1538 objstruct = type.objstruct_cname
1539 else:
1540 objstruct = "struct %s" % type.objstruct_cname
1541 code.putln('%s = __Pyx_ImportType("%s", "%s", sizeof(%s)); if (!%s) %s' % (
1542 type.typeptr_cname,
1543 type.module_name,
1544 type.name,
1545 objstruct,
1546 type.typeptr_cname,
1547 error_code))
1549 def generate_type_ready_code(self, env, entry, code):
1550 # Generate a call to PyType_Ready for an extension
1551 # type defined in this module.
1552 type = entry.type
1553 typeobj_cname = type.typeobj_cname
1554 scope = type.scope
1555 if scope: # could be None if there was an error
1556 if entry.visibility <> 'extern':
1557 for slot in TypeSlots.slot_table:
1558 slot.generate_dynamic_init_code(scope, code)
1559 code.putln(
1560 "if (PyType_Ready(&%s) < 0) %s" % (
1561 typeobj_cname,
1562 code.error_goto(entry.pos)))
1563 if type.vtable_cname:
1564 code.putln(
1565 "if (__Pyx_SetVtable(%s.tp_dict, %s) < 0) %s" % (
1566 typeobj_cname,
1567 type.vtabptr_cname,
1568 code.error_goto(entry.pos)))
1569 code.use_utility_code(Nodes.set_vtable_utility_code)
1570 code.putln(
1571 'if (PyObject_SetAttrString(%s, "%s", (PyObject *)&%s) < 0) %s' % (
1572 Naming.module_cname,
1573 scope.class_name,
1574 typeobj_cname,
1575 code.error_goto(entry.pos)))
1576 weakref_entry = scope.lookup_here("__weakref__")
1577 if weakref_entry:
1578 if weakref_entry.type is py_object_type:
1579 tp_weaklistoffset = "%s.tp_weaklistoffset" % typeobj_cname
1580 code.putln("if (%s == 0) %s = offsetof(struct %s, %s);" % (
1581 tp_weaklistoffset,
1582 tp_weaklistoffset,
1583 type.objstruct_cname,
1584 weakref_entry.cname))
1585 else:
1586 error(weakref_entry.pos, "__weakref__ slot must be of type 'object'")
1588 def generate_exttype_vtable_init_code(self, entry, code):
1589 # Generate code to initialise the C method table of an
1590 # extension type.
1591 type = entry.type
1592 if type.vtable_cname:
1593 code.putln(
1594 "%s = &%s;" % (
1595 type.vtabptr_cname,
1596 type.vtable_cname))
1597 if type.base_type and type.base_type.vtabptr_cname:
1598 code.putln(
1599 "%s.%s = *%s;" % (
1600 type.vtable_cname,
1601 Naming.obj_base_cname,
1602 type.base_type.vtabptr_cname))
1603 for meth_entry in type.scope.cfunc_entries:
1604 if meth_entry.func_cname:
1605 code.putln(
1606 "*(void(**)(void))&%s.%s = (void(*)(void))%s;" % (
1607 type.vtable_cname,
1608 meth_entry.cname,
1609 meth_entry.func_cname))
1611 def generate_typeptr_assignment_code(self, entry, code):
1612 # Generate code to initialise the typeptr of an extension
1613 # type defined in this module to point to its type object.
1614 type = entry.type
1615 if type.typeobj_cname:
1616 code.putln(
1617 "%s = &%s;" % (
1618 type.typeptr_cname, type.typeobj_cname))
1620 def generate_utility_functions(self, code):
1621 code.global_state.generate_utility_functions(code)
1623 #------------------------------------------------------------------------------------
1625 # Runtime support code
1627 #------------------------------------------------------------------------------------
1629 import_module_utility_code = [
1630 """
1631 static PyObject *__Pyx_ImportModule(char *name); /*proto*/
1632 ""","""
1633 #ifndef __PYX_HAVE_RT_ImportModule
1634 #define __PYX_HAVE_RT_ImportModule
1635 static PyObject *__Pyx_ImportModule(char *name) {
1636 PyObject *py_name = 0;
1638 py_name = PyString_FromString(name);
1639 if (!py_name)
1640 goto bad;
1641 return PyImport_Import(py_name);
1642 bad:
1643 Py_XDECREF(py_name);
1644 return 0;
1646 #endif
1647 """]
1649 #------------------------------------------------------------------------------------
1651 type_import_utility_code = [
1652 """
1653 static PyTypeObject *__Pyx_ImportType(char *module_name, char *class_name, long size); /*proto*/
1654 ""","""
1655 #ifndef __PYX_HAVE_RT_ImportType
1656 #define __PYX_HAVE_RT_ImportType
1657 static PyTypeObject *__Pyx_ImportType(char *module_name, char *class_name,
1658 long size)
1660 PyObject *py_module = 0;
1661 PyObject *result = 0;
1663 py_module = __Pyx_ImportModule(module_name);
1664 if (!py_module)
1665 goto bad;
1666 result = PyObject_GetAttrString(py_module, class_name);
1667 if (!result)
1668 goto bad;
1669 if (!PyType_Check(result)) {
1670 PyErr_Format(PyExc_TypeError,
1671 "%s.%s is not a type object",
1672 module_name, class_name);
1673 goto bad;
1675 if (((PyTypeObject *)result)->tp_basicsize != size) {
1676 PyErr_Format(PyExc_ValueError,
1677 "%s.%s does not appear to be the correct type object",
1678 module_name, class_name);
1679 goto bad;
1681 return (PyTypeObject *)result;
1682 bad:
1683 Py_XDECREF(result);
1684 return 0;
1686 #endif
1687 """]
1689 #------------------------------------------------------------------------------------
1691 function_export_utility_code = [
1692 """
1693 static int __Pyx_ExportFunction(char *n, void *f, char *s); /*proto*/
1694 """,r"""
1695 static int __Pyx_ExportFunction(char *n, void *f, char *s) {
1696 PyObject *d = 0;
1697 PyObject *p = 0;
1698 d = PyObject_GetAttrString(%(MODULE)s, "%(API)s");
1699 if (!d) {
1700 PyErr_Clear();
1701 d = PyDict_New();
1702 if (!d)
1703 goto bad;
1704 Py_INCREF(d);
1705 if (PyModule_AddObject(%(MODULE)s, "%(API)s", d) < 0)
1706 goto bad;
1708 p = PyCObject_FromVoidPtrAndDesc(f, s, 0);
1709 if (!p)
1710 goto bad;
1711 if (PyDict_SetItemString(d, n, p) < 0)
1712 goto bad;
1713 Py_DECREF(d);
1714 return 0;
1715 bad:
1716 Py_XDECREF(p);
1717 Py_XDECREF(d);
1718 return -1;
1720 """ % {'MODULE': Naming.module_cname, 'API': Naming.api_name}]
1722 #------------------------------------------------------------------------------------
1724 function_import_utility_code = [
1725 """
1726 static int __Pyx_ImportFunction(PyObject *module, char *funcname, void **f, char *sig); /*proto*/
1727 ""","""
1728 #ifndef __PYX_HAVE_RT_ImportFunction
1729 #define __PYX_HAVE_RT_ImportFunction
1730 static int __Pyx_ImportFunction(PyObject *module, char *funcname, void **f, char *sig) {
1731 PyObject *d = 0;
1732 PyObject *cobj = 0;
1733 char *desc;
1735 d = PyObject_GetAttrString(module, "%(API)s");
1736 if (!d)
1737 goto bad;
1738 cobj = PyDict_GetItemString(d, funcname);
1739 if (!cobj) {
1740 PyErr_Format(PyExc_ImportError,
1741 "%%s does not export expected C function %%s",
1742 PyModule_GetName(module), funcname);
1743 goto bad;
1745 desc = (char *)PyCObject_GetDesc(cobj);
1746 if (!desc)
1747 goto bad;
1748 if (strcmp(desc, sig) != 0) {
1749 PyErr_Format(PyExc_TypeError,
1750 "C function %%s.%%s has wrong signature (expected %%s, got %%s)",
1751 PyModule_GetName(module), funcname, sig, desc);
1752 goto bad;
1754 *f = PyCObject_AsVoidPtr(cobj);
1755 Py_DECREF(d);
1756 return 0;
1757 bad:
1758 Py_XDECREF(d);
1759 return -1;
1761 #endif
1762 """ % dict(API = Naming.api_name)]