def generate_c_module(self) -> str: emitter = Emitter(self.context) self.declare_imports(self.module.imports) for cl in self.module.classes: generate_class(cl, self.module_name, emitter) for fn in self.module.functions: generate_function_declaration(fn, emitter) emitter.emit_line() self.generate_module_def(emitter) for fn in self.module.functions: emitter.emit_line() generate_native_function(fn, emitter) emitter.emit_line() generate_wrapper_function(fn, emitter) declarations = Emitter(self.context) declarations.emit_line('#include <Python.h>') declarations.emit_line('#include <CPy.h>') declarations.emit_line() for declaration in self.toposort_declarations(): declarations.emit_lines(*declaration.body) return ''.join(declarations.fragments + emitter.fragments)
def generate_c_for_modules(self) -> str: emitter = Emitter(self.context) module_irs = [module_ir for _, module_ir in self.modules] for module_name, module in self.modules: self.declare_module(module_name, emitter) self.declare_internal_globals(module_name, emitter) self.declare_imports(module.imports, emitter) for identifier in self.literals.values(): self.declare_static_pyobject(identifier, emitter) for module in module_irs: for fn in module.functions: generate_function_declaration(fn, emitter) self.generate_literals(emitter) classes = [] for module_name, module in self.modules: classes.extend([(module_name, cl) for cl in module.classes]) # We must topo sort so that base classes are generated first. classes = sort_classes(classes) for module_name, cl in classes: generate_class_type_decl(cl, emitter) for module_name, cl in classes: generate_class(cl, module_name, emitter) emitter.emit_line() # Generate Python extension module definitions and module initialization functions. for module_name, module in self.modules: self.generate_module_def(emitter, module_name, module) for module_name, module in self.modules: for fn in module.functions: emitter.emit_line() generate_native_function(fn, emitter, self.source_paths[module_name], module_name) if fn.name != TOP_LEVEL_NAME: emitter.emit_line() generate_wrapper_function(fn, emitter) declarations = Emitter(self.context) declarations.emit_line('#include <Python.h>') declarations.emit_line('#include <CPy.h>') declarations.emit_line() for declaration in self.toposort_declarations(): declarations.emit_lines(*declaration.body) for static_def in self.context.statics.values(): declarations.emit_line(static_def) return ''.join(declarations.fragments + emitter.fragments)
def generate_c_for_modules(self) -> List[Tuple[str, str]]: file_contents = [] multi_file = self.use_shared_lib and self.multi_file base_emitter = Emitter(self.context) base_emitter.emit_line('#include "__native.h"') emitter = base_emitter for (_, literal), identifier in self.literals.items(): if isinstance(literal, int): symbol = emitter.static_name(identifier, None) self.declare_global('CPyTagged ', symbol) else: self.declare_static_pyobject(identifier, emitter) for module_name, module in self.modules: if multi_file: emitter = Emitter(self.context) emitter.emit_line('#include "__native.h"') self.declare_module(module_name, emitter) self.declare_internal_globals(module_name, emitter) self.declare_imports(module.imports, emitter) # Finals must be last (types can depend on declared above) self.define_finals(module.final_names, emitter) for cl in module.classes: generate_class(cl, module_name, emitter) # Generate Python extension module definitions and module initialization functions. self.generate_module_def(emitter, module_name, module) for fn in module.functions: emitter.emit_line() generate_native_function(fn, emitter, self.source_paths[module_name], module_name) if fn.name != TOP_LEVEL_NAME: emitter.emit_line() generate_wrapper_function(fn, emitter) if multi_file: name = ('__native_{}.c'.format(emitter.names.private_name(module_name))) file_contents.append((name, ''.join(emitter.fragments))) sorted_decls = self.toposort_declarations() emitter = base_emitter self.generate_globals_init(emitter) for declaration in sorted_decls: if declaration.defn: emitter.emit_lines(*declaration.defn) emitter.emit_line() declarations = Emitter(self.context) declarations.emit_line('#include <Python.h>') declarations.emit_line('#include <CPy.h>') declarations.emit_line() declarations.emit_line('int CPyGlobalsInit(void);') declarations.emit_line() for declaration in sorted_decls: if declaration.needs_extern: declarations.emit_lines( 'extern {}'.format(declaration.decl[0]), *declaration.decl[1:]) emitter.emit_lines(*declaration.decl) else: declarations.emit_lines(*declaration.decl) for module_name, module in self.modules: self.declare_finals(module.final_names, declarations) for cl in module.classes: generate_class_type_decl(cl, emitter, declarations) for fn in module.functions: generate_function_declaration(fn, declarations) if self.shared_lib_name: self.generate_shared_lib_init(emitter) return file_contents + [('__native.c', ''.join(emitter.fragments)), ('__native.h', ''.join(declarations.fragments))]
def generate_c_for_modules(self) -> List[Tuple[str, str]]: file_contents = [] multi_file = self.use_shared_lib and self.multi_file base_emitter = Emitter(self.context) # When not in multi-file mode we just include the runtime # library c files to reduce the number of compiler invocations # needed if not self.multi_file: base_emitter.emit_line('#include "CPy.c"') base_emitter.emit_line('#include "getargs.c"') base_emitter.emit_line('#include "__native{}.h"'.format( self.group_suffix)) base_emitter.emit_line('#include "__native_internal{}.h"'.format( self.group_suffix)) emitter = base_emitter for (_, literal), identifier in self.literals.items(): if isinstance(literal, int): symbol = emitter.static_name(identifier, None) self.declare_global('CPyTagged ', symbol) else: self.declare_static_pyobject(identifier, emitter) for module_name, module in self.modules: if multi_file: emitter = Emitter(self.context) emitter.emit_line('#include "__native{}.h"'.format( self.group_suffix)) emitter.emit_line('#include "__native_internal{}.h"'.format( self.group_suffix)) self.declare_module(module_name, emitter) self.declare_internal_globals(module_name, emitter) self.declare_imports(module.imports, emitter) for cl in module.classes: if cl.is_ext_class: generate_class(cl, module_name, emitter) # Generate Python extension module definitions and module initialization functions. self.generate_module_def(emitter, module_name, module) for fn in module.functions: emitter.emit_line() generate_native_function(fn, emitter, self.source_paths[module_name], module_name) if fn.name != TOP_LEVEL_NAME: emitter.emit_line() generate_wrapper_function(fn, emitter, self.source_paths[module_name], module_name) if multi_file: name = ('__native_{}.c'.format( emitter.names.private_name(module_name))) file_contents.append((name, ''.join(emitter.fragments))) # The external header file contains type declarations while # the internal contains declarations of functions and objects # (which are shared between shared libraries via dynamic # exports tables and not accessed directly.) ext_declarations = Emitter(self.context) ext_declarations.emit_line('#ifndef MYPYC_NATIVE{}_H'.format( self.group_suffix)) ext_declarations.emit_line('#define MYPYC_NATIVE{}_H'.format( self.group_suffix)) ext_declarations.emit_line('#include <Python.h>') ext_declarations.emit_line('#include <CPy.h>') declarations = Emitter(self.context) declarations.emit_line('#ifndef MYPYC_NATIVE_INTERNAL{}_H'.format( self.group_suffix)) declarations.emit_line('#define MYPYC_NATIVE_INTERNAL{}_H'.format( self.group_suffix)) declarations.emit_line('#include <Python.h>') declarations.emit_line('#include <CPy.h>') declarations.emit_line('#include "__native{}.h"'.format( self.group_suffix)) declarations.emit_line() declarations.emit_line('int CPyGlobalsInit(void);') declarations.emit_line() for module_name, module in self.modules: self.declare_finals(module_name, module.final_names, declarations) for cl in module.classes: generate_class_type_decl(cl, emitter, ext_declarations, declarations) for fn in module.functions: generate_function_declaration(fn, declarations) for lib in sorted(self.context.group_deps): declarations.emit_lines( '#include "__native_{}.h"'.format(lib), 'struct export_table_{} exports_{};'.format(lib, lib)) sorted_decls = self.toposort_declarations() emitter = base_emitter self.generate_globals_init(emitter) emitter.emit_line() for declaration in sorted_decls: decls = ext_declarations if declaration.is_type else declarations if not declaration.is_type: decls.emit_lines('extern {}'.format(declaration.decl[0]), *declaration.decl[1:]) # If there is a definition, emit it. Otherwise repeat the declaration # (without an extern). if declaration.defn: emitter.emit_lines(*declaration.defn) else: emitter.emit_lines(*declaration.decl) else: decls.emit_lines(*declaration.decl) if self.group_name: self.generate_export_table(ext_declarations, emitter) self.generate_shared_lib_init(emitter) ext_declarations.emit_line('#endif') declarations.emit_line('#endif') return file_contents + [ ('__native{}.c'.format(self.group_suffix), ''.join( emitter.fragments)), ('__native_internal{}.h'.format(self.group_suffix), ''.join( declarations.fragments)), ('__native{}.h'.format(self.group_suffix), ''.join( ext_declarations.fragments)), ]
def generate_c_for_modules(self) -> List[Tuple[str, str]]: file_contents = [] multi_file = self.use_shared_lib and self.multi_file base_emitter = Emitter(self.context) base_emitter.emit_line('#include "__native.h"') emitter = base_emitter for (_, literal), identifier in self.literals.items(): if isinstance(literal, int): symbol = emitter.static_name(identifier, None) self.declare_global('CPyTagged ', symbol) else: self.declare_static_pyobject(identifier, emitter) for module_name, module in self.modules: if multi_file: emitter = Emitter(self.context) emitter.emit_line('#include "__native.h"') self.declare_module(module_name, emitter) self.declare_internal_globals(module_name, emitter) self.declare_imports(module.imports, emitter) # Finals must be last (types can depend on declared above) self.define_finals(module.final_names, emitter) for cl in module.classes: generate_class(cl, module_name, emitter) # Generate Python extension module definitions and module initialization functions. self.generate_module_def(emitter, module_name, module) for fn in module.functions: emitter.emit_line() generate_native_function(fn, emitter, self.source_paths[module_name], module_name) if fn.name != TOP_LEVEL_NAME: emitter.emit_line() generate_wrapper_function(fn, emitter) if multi_file: name = ('__native_{}.c'.format( emitter.names.private_name(module_name))) file_contents.append((name, ''.join(emitter.fragments))) sorted_decls = self.toposort_declarations() emitter = base_emitter self.generate_globals_init(emitter) for declaration in sorted_decls: if declaration.defn: emitter.emit_lines(*declaration.defn) emitter.emit_line() # Generate a dummy initialization function for the shared lib, # since the windows linker gets mad if it isn't present. if self.shared_lib_name: emitter.emit_line() emitter.emit_lines( 'PyMODINIT_FUNC PyInit_lib{}(void)'.format( self.shared_lib_name), '{', 'PyErr_SetString(PyExc_RuntimeError, "mypyc shared lib is not to be imported");', 'return NULL;', '}', ) declarations = Emitter(self.context) declarations.emit_line('#include <Python.h>') declarations.emit_line('#include <CPy.h>') declarations.emit_line() declarations.emit_line('int CPyGlobalsInit(void);') declarations.emit_line() for declaration in sorted_decls: declarations.emit_lines(*declaration.decl) for module_name, module in self.modules: self.declare_finals(module.final_names, declarations) for cl in module.classes: generate_class_type_decl(cl, declarations) for fn in module.functions: generate_function_declaration(fn, declarations) return file_contents + [('__native.c', ''.join(emitter.fragments)), ('__native.h', ''.join(declarations.fragments)) ]
def generate_c_for_modules(self) -> List[Tuple[str, str]]: file_contents = [] multi_file = self.use_shared_lib and self.multi_file base_emitter = Emitter(self.context) base_emitter.emit_line('#include "__native.h"') base_emitter.emit_line('#include "__native_internal.h"') emitter = base_emitter for (_, literal), identifier in self.literals.items(): if isinstance(literal, int): symbol = emitter.static_name(identifier, None) self.declare_global('CPyTagged ', symbol) else: self.declare_static_pyobject(identifier, emitter) for module_name, module in self.modules: if multi_file: emitter = Emitter(self.context) emitter.emit_line('#include "__native.h"') emitter.emit_line('#include "__native_internal.h"') self.declare_module(module_name, emitter) self.declare_internal_globals(module_name, emitter) self.declare_imports(module.imports, emitter) # Finals must be last (types can depend on declared above) self.define_finals(module_name, module.final_names, emitter) for cl in module.classes: if cl.is_ext_class: generate_class(cl, module_name, emitter) # Generate Python extension module definitions and module initialization functions. self.generate_module_def(emitter, module_name, module) for fn in module.functions: emitter.emit_line() generate_native_function(fn, emitter, self.source_paths[module_name], module_name) if fn.name != TOP_LEVEL_NAME: emitter.emit_line() generate_wrapper_function( fn, emitter, self.source_paths[module_name], module_name) if multi_file: name = ('__native_{}.c'.format(emitter.names.private_name(module_name))) file_contents.append((name, ''.join(emitter.fragments))) # The external header file contains type declarations while # the internal contains declarations of functions and objects # (which are shared between shared libraries via dynamic # linking tables and not accessed directly.) ext_declarations = Emitter(self.context) ext_declarations.emit_line('#ifndef MYPYC_NATIVE_H') ext_declarations.emit_line('#define MYPYC_NATIVE_H') ext_declarations.emit_line('#include <Python.h>') ext_declarations.emit_line('#include <CPy.h>') declarations = Emitter(self.context) declarations.emit_line('#ifndef MYPYC_NATIVE_INTERNAL_H') declarations.emit_line('#define MYPYC_NATIVE_INTERNAL_H') declarations.emit_line('#include <Python.h>') declarations.emit_line('#include <CPy.h>') declarations.emit_line('#include "__native.h"') declarations.emit_line() declarations.emit_line('int CPyGlobalsInit(void);') declarations.emit_line() for module_name, module in self.modules: self.declare_finals(module_name, module.final_names, declarations) for cl in module.classes: generate_class_type_decl(cl, emitter, ext_declarations, declarations) for fn in module.functions: generate_function_declaration(fn, declarations) sorted_decls = self.toposort_declarations() emitter = base_emitter self.generate_globals_init(emitter) for declaration in sorted_decls: if declaration.defn: emitter.emit_lines(*declaration.defn) emitter.emit_line() for declaration in sorted_decls: decls = ext_declarations if declaration.is_type else declarations if not declaration.is_type: decls.emit_lines( 'extern {}'.format(declaration.decl[0]), *declaration.decl[1:]) emitter.emit_lines(*declaration.decl) else: decls.emit_lines(*declaration.decl) if self.shared_lib_name: self.generate_shared_lib_init(emitter) ext_declarations.emit_line('#endif') declarations.emit_line('#endif') return file_contents + [('__native.c', ''.join(emitter.fragments)), ('__native_internal.h', ''.join(declarations.fragments)), ('__native.h', ''.join(ext_declarations.fragments)), ]