remove trailing whitespace
[cython.git] / Cython / Compiler / ModuleNode.py
index eebfd14e5a8875e5575810c60ffe05d57503014d..738d13600b27da6a71e8cfed42d2c659d45afc13 100644 (file)
@@ -96,14 +96,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 f.close()
 
     def generate_h_code(self, env, options, result):
-        def h_entries(entries, pxd = 0):
+        def h_entries(entries, api=0, pxd=0):
             return [entry for entry in entries
-                if entry.visibility == 'public' or pxd and entry.defined_in_pxd]
-        h_types = h_entries(env.type_entries)
+                    if ((entry.visibility == 'public') or
+                        (api and entry.api) or
+                        (pxd and entry.defined_in_pxd))]
+        h_types = h_entries(env.type_entries, api=1)
         h_vars = h_entries(env.var_entries)
         h_funcs = h_entries(env.cfunc_entries)
         h_extension_types = h_entries(env.c_class_entries)
-        if h_types or h_vars or h_funcs or h_extension_types:
+        if (h_types or  h_vars or h_funcs or h_extension_types):
             result.h_file = replace_suffix(result.c_file, ".h")
             h_code = Code.CCodeWriter()
             Code.GlobalState(h_code)
@@ -112,32 +114,40 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 i_code = Code.PyrexCodeWriter(result.i_file)
             else:
                 i_code = None
-            guard = Naming.h_guard_prefix + env.qualified_name.replace(".", "__")
-            h_code.put_h_guard(guard)
-            self.generate_extern_c_macro_definition(h_code)
+
+            h_guard = Naming.h_guard_prefix + self.api_name(env)
+            h_code.put_h_guard(h_guard)
+            h_code.putln("")
             self.generate_type_header_code(h_types, h_code)
             h_code.putln("")
-            h_code.putln("#ifndef %s" % Naming.api_guard_prefix + self.api_name(env))
-            if h_vars:
-                h_code.putln("")
-                for entry in h_vars:
-                    self.generate_public_declaration(entry, h_code, i_code)
-            if h_funcs:
-                h_code.putln("")
-                for entry in h_funcs:
-                    self.generate_public_declaration(entry, h_code, i_code)
+            api_guard = Naming.api_guard_prefix + self.api_name(env)
+            h_code.putln("#ifndef %s" % api_guard)
+            h_code.putln("")
+            self.generate_extern_c_macro_definition(h_code)
             if h_extension_types:
                 h_code.putln("")
                 for entry in h_extension_types:
                     self.generate_cclass_header_code(entry.type, h_code)
                     if i_code:
                         self.generate_cclass_include_code(entry.type, i_code)
+            if h_funcs:
+                h_code.putln("")
+                for entry in h_funcs:
+                    self.generate_public_declaration(entry, h_code, i_code)
+            if h_vars:
+                h_code.putln("")
+                for entry in h_vars:
+                    self.generate_public_declaration(entry, h_code, i_code)
             h_code.putln("")
-            h_code.putln("#endif")
+            h_code.putln("#endif /* !%s */" % api_guard)
             h_code.putln("")
+            h_code.putln("#if PY_MAJOR_VERSION < 3")
             h_code.putln("PyMODINIT_FUNC init%s(void);" % env.module_name)
-            h_code.putln("")
+            h_code.putln("#else")
+            h_code.putln("PyMODINIT_FUNC PyInit_%s(void);" % env.module_name)
             h_code.putln("#endif")
+            h_code.putln("")
+            h_code.putln("#endif /* !%s */" % h_guard)
 
             f = open_new_file(result.h_file)
             try:
@@ -158,63 +168,68 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         return env.qualified_name.replace(".", "__")
 
     def generate_api_code(self, env, result):
-        api_funcs = []
-        public_extension_types = []
-        has_api_extension_types = 0
-        for entry in env.cfunc_entries:
-            if entry.api:
-                api_funcs.append(entry)
-        for entry in env.c_class_entries:
-            if entry.visibility == 'public':
-                public_extension_types.append(entry)
-            if entry.api:
-                has_api_extension_types = 1
-        if api_funcs or has_api_extension_types:
+        def api_entries(entries, pxd=0):
+            return [entry for entry in entries
+                    if entry.api or (pxd and entry.defined_in_pxd)]
+        api_vars = api_entries(env.var_entries)
+        api_funcs = api_entries(env.cfunc_entries)
+        api_extension_types = api_entries(env.c_class_entries)
+        if api_vars or api_funcs or api_extension_types:
             result.api_file = replace_suffix(result.c_file, "_api.h")
             h_code = Code.CCodeWriter()
             Code.GlobalState(h_code)
-            name = self.api_name(env)
-            guard = Naming.api_guard_prefix + name
-            h_code.put_h_guard(guard)
+            api_guard = Naming.api_guard_prefix + self.api_name(env)
+            h_code.put_h_guard(api_guard)
             h_code.putln('#include "Python.h"')
             if result.h_file:
                 h_code.putln('#include "%s"' % os.path.basename(result.h_file))
-            for entry in public_extension_types:
-                type = entry.type
+            if api_extension_types:
                 h_code.putln("")
-                h_code.putln("static PyTypeObject *%s;" % type.typeptr_cname)
-                h_code.putln("#define %s (*%s)" % (
-                    type.typeobj_cname, type.typeptr_cname))
+                for entry in api_extension_types:
+                    type = entry.type
+                    h_code.putln("static PyTypeObject *%s = 0;" % type.typeptr_cname)
+                    h_code.putln("#define %s (*%s)" % (
+                        type.typeobj_cname, type.typeptr_cname))
             if api_funcs:
                 h_code.putln("")
                 for entry in api_funcs:
                     type = CPtrType(entry.type)
-                    h_code.putln("static %s;" % type.declaration_code(entry.cname))
-            h_code.putln("")
-            h_code.put_h_guard(Naming.api_func_guard + "import_module")
+                    cname = env.mangle(Naming.func_prefix, entry.name)
+                    h_code.putln("static %s = 0;" % type.declaration_code(cname))
+                    h_code.putln("#define %s %s" % (entry.name, cname))
+            if api_vars:
+                h_code.putln("")
+                for entry in api_vars:
+                    type = CPtrType(entry.type)
+                    cname = env.mangle(Naming.var_prefix, entry.name)
+                    h_code.putln("static %s = 0;" %  type.declaration_code(cname))
+                    h_code.putln("#define %s (*%s)" % (entry.name, cname))
             h_code.put(import_module_utility_code.impl)
-            h_code.putln("")
-            h_code.putln("#endif")
+            if api_vars:
+                h_code.put(voidptr_import_utility_code.impl)
             if api_funcs:
-                h_code.putln("")
                 h_code.put(function_import_utility_code.impl)
-            if public_extension_types:
-                h_code.putln("")
+            if api_extension_types:
                 h_code.put(type_import_utility_code.impl)
             h_code.putln("")
-            h_code.putln("static int import_%s(void) {" % name)
+            h_code.putln("static int import_%s(void) {" % self.api_name(env))
             h_code.putln("PyObject *module = 0;")
             h_code.putln('module = __Pyx_ImportModule("%s");' % env.qualified_name)
             h_code.putln("if (!module) goto bad;")
             for entry in api_funcs:
+                cname = env.mangle(Naming.func_prefix, entry.name)
                 sig = entry.type.signature_string()
                 h_code.putln(
-                    'if (__Pyx_ImportFunction(module, "%s", (void (**)(void))&%s, "%s") < 0) goto bad;' % (
-                        entry.name,
-                        entry.cname,
-                        sig))
+                    'if (__Pyx_ImportFunction(module, "%s", (void (**)(void))&%s, "%s") < 0) goto bad;'
+                    % (entry.name, cname, sig))
+            for entry in api_vars:
+                cname = env.mangle(Naming.var_prefix, entry.name)
+                sig = entry.type.declaration_code("")
+                h_code.putln(
+                    'if (__Pyx_ImportVoidPtr(module, "%s", (void **)&%s, "%s") < 0) goto bad;'
+                    % (entry.name, cname, sig))
             h_code.putln("Py_DECREF(module); module = 0;")
-            for entry in public_extension_types:
+            for entry in api_extension_types:
                 self.generate_type_import_call(
                     entry.type, h_code,
                     "if (!%s) goto bad;" % entry.type.typeptr_cname)
@@ -224,7 +239,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             h_code.putln("return -1;")
             h_code.putln("}")
             h_code.putln("")
-            h_code.putln("#endif")
+            h_code.putln("#endif /* !%s */" % api_guard)
 
             f = open_new_file(result.api_file)
             try:
@@ -233,8 +248,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 f.close()
 
     def generate_cclass_header_code(self, type, h_code):
-        h_code.putln("%s DL_IMPORT(PyTypeObject) %s;" % (
+        h_code.putln("%s %s %s;" % (
             Naming.extern_c_macro,
+            PyrexTypes.public_decl("PyTypeObject", "DL_IMPORT"),
             type.typeobj_cname))
 
     def generate_cclass_include_code(self, type, i_code):
@@ -272,7 +288,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
 
         code = globalstate['before_global_var']
         code.putln('#define __Pyx_MODULE_NAME "%s"' % self.full_module_name)
-        code.putln("static int %s%s = 0;" % (Naming.module_is_main, self.full_module_name.replace('.', '__')))
+        code.putln("int %s%s = 0;" % (Naming.module_is_main, self.full_module_name.replace('.', '__')))
         code.putln("")
         code.putln("/* Implementation of %s */" % env.qualified_name)
 
@@ -424,8 +440,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                         self.generate_objstruct_definition(type, code)
         for entry in vtabslot_list:
             self.generate_objstruct_definition(entry.type, code)
+            self.generate_typeobj_predeclaration(entry, code)
         for entry in vtab_list:
-            self.generate_typeobject_predeclaration(entry, code)
+            self.generate_typeobj_predeclaration(entry, code)
             self.generate_exttype_vtable_struct(entry, code)
             self.generate_exttype_vtabptr_declaration(entry, code)
 
@@ -610,6 +627,15 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
   #define PyBoolObject                 PyLongObject
 #endif
 
+#if PY_VERSION_HEX < 0x03020000
+  typedef long Py_hash_t;
+  #define __Pyx_PyInt_FromHash_t PyInt_FromLong
+  #define __Pyx_PyInt_AsHash_t   PyInt_AsLong
+#else
+  #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t
+  #define __Pyx_PyInt_AsHash_t   PyInt_AsSsize_t
+#endif
+
 """)
 
         code.put("""
@@ -676,6 +702,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("#define _USE_MATH_DEFINES")
         code.putln("#endif")
         code.putln("#include <math.h>")
+        code.putln("#define %s" % Naming.h_guard_prefix + self.api_name(env))
         code.putln("#define %s" % Naming.api_guard_prefix + self.api_name(env))
         self.generate_includes(env, cimported_modules, code)
         code.putln("")
@@ -712,10 +739,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
 
     def generate_extern_c_macro_definition(self, code):
         name = Naming.extern_c_macro
-        code.putln("#ifdef __cplusplus")
-        code.putln('#define %s extern "C"' % name)
-        code.putln("#else")
-        code.putln("#define %s extern" % name)
+        code.putln("#ifndef %s" % name)
+        code.putln("  #ifdef __cplusplus")
+        code.putln('    #define %s extern "C"' % name)
+        code.putln("  #else")
+        code.putln("    #define %s extern" % name)
+        code.putln("  #endif")
         code.putln("#endif")
 
     def generate_includes(self, env, cimported_modules, code):
@@ -777,10 +806,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
     def generate_typedef(self, entry, code):
         base_type = entry.type.typedef_base_type
         if base_type.is_numeric:
-            writer = code.globalstate['numeric_typedefs']
+            try:
+                writer = code.globalstate['numeric_typedefs']
+            except KeyError:
+                writer = code
         else:
             writer = code
-        writer.putln("")
+        writer.mark_pos(entry.pos)
         writer.putln("typedef %s;" % base_type.declaration_code(entry.cname))
 
     def sue_header_footer(self, type, kind, name):
@@ -804,7 +836,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 code.globalstate.use_utility_code(packed_struct_utility_code)
             header, footer = \
                 self.sue_header_footer(type, kind, type.cname)
-            code.putln("")
             if packed:
                 code.putln("#if defined(__SUNPRO_C)")
                 code.putln("  #pragma pack(1)")
@@ -835,7 +866,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         name = entry.cname or entry.name or ""
         header, footer = \
             self.sue_header_footer(type, "enum", name)
-        code.putln("")
         code.putln(header)
         enum_values = entry.enum_values
         if not enum_values:
@@ -861,21 +891,23 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 code.putln(value_code)
         code.putln(footer)
 
-    def generate_typeobject_predeclaration(self, entry, code):
+    def generate_typeobj_predeclaration(self, entry, code):
         code.putln("")
         name = entry.type.typeobj_cname
         if name:
             if entry.visibility == 'extern' and not entry.in_cinclude:
-                code.putln("%s DL_IMPORT(PyTypeObject) %s;" % (
+                code.putln("%s %s %s;" % (
                     Naming.extern_c_macro,
+                    PyrexTypes.public_decl("PyTypeObject", "DL_IMPORT"),
                     name))
             elif entry.visibility == 'public':
-                code.putln("%s DL_EXPORT(PyTypeObject) %s;" % (
+                code.putln("%s %s %s;" % (
                     Naming.extern_c_macro,
+                    PyrexTypes.public_decl("PyTypeObject", "DL_EXPORT"),
                     name))
             # ??? Do we really need the rest of this? ???
             #else:
-            #    code.putln("staticforward PyTypeObject %s;" % name)
+            #    code.putln("static PyTypeObject %s;" % name)
 
     def generate_exttype_vtable_struct(self, entry, code):
         code.mark_pos(entry.pos)
@@ -915,7 +947,6 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             return # Forward declared but never defined
         header, footer = \
             self.sue_header_footer(type, "struct", type.objstruct_cname)
-        code.putln("")
         code.putln(header)
         base_type = type.base_type
         if base_type:
@@ -933,9 +964,13 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                     type.vtabstruct_cname,
                     type.vtabslot_cname))
         for attr in type.scope.var_entries:
+            if attr.is_declared_generic:
+                attr_type = py_object_type
+            else:
+                attr_type = attr.type
             code.putln(
                 "%s;" %
-                    attr.type.declaration_code(attr.cname))
+                    attr_type.declaration_code(attr.cname))
         code.putln(footer)
         if type.objtypedef_cname is not None:
             # Only for exposing public typedef name.
@@ -954,24 +989,26 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         for entry in env.cfunc_entries:
             if entry.inline_func_in_pxd or (not entry.in_cinclude and (definition
                     or entry.defined_in_pxd or entry.visibility == 'extern')):
-                if entry.visibility in ('public', 'extern'):
+                if entry.visibility == 'public':
+                    storage_class = "%s " % Naming.extern_c_macro
                     dll_linkage = "DL_EXPORT"
+                elif entry.visibility == 'extern':
+                    storage_class = "%s " % Naming.extern_c_macro
+                    dll_linkage = "DL_IMPORT"
+                elif entry.visibility == 'private':
+                    storage_class = "static "
+                    dll_linkage = None
                 else:
+                    storage_class = "static "
                     dll_linkage = None
                 type = entry.type
+
                 if not definition and entry.defined_in_pxd:
                     type = CPtrType(type)
                 header = type.declaration_code(entry.cname,
-                    dll_linkage = dll_linkage)
-                if entry.visibility == 'private':
-                    storage_class = "static "
-                elif entry.visibility == 'public':
-                    storage_class = ""
-                else:
-                    storage_class = "%s " % Naming.extern_c_macro
+                                               dll_linkage = dll_linkage)
                 if entry.func_modifiers:
-                    modifiers = '%s ' % ' '.join([
-                            modifier.upper() for modifier in entry.func_modifiers])
+                    modifiers = "%s " % ' '.join(entry.func_modifiers).upper()
                 else:
                     modifiers = ''
                 code.putln("%s%s%s; /*proto*/" % (
@@ -1232,7 +1269,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         for entry in py_attrs:
             name = "p->%s" % entry.cname
             code.putln("tmp = ((PyObject*)%s);" % name)
-            code.put_init_to_py_none(name, entry.type, nanny=False)
+            if entry.is_declared_generic:
+                code.put_init_to_py_none(name, py_object_type, nanny=False)
+            else:
+                code.put_init_to_py_none(name, entry.type, nanny=False)
             code.putln("Py_XDECREF(tmp);")
         code.putln(
             "return 0;")
@@ -1736,8 +1776,8 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("{")
         tempdecl_code = code.insertion_point()
 
+        code.put_declare_refcount_context()
         code.putln("#if CYTHON_REFNANNY")
-        code.putln("void* __pyx_refnanny = NULL;")
         code.putln("__Pyx_RefNanny = __Pyx_RefNannyImportAPI(\"refnanny\");")
         code.putln("if (!__Pyx_RefNanny) {")
         code.putln("  PyErr_Clear();")
@@ -1745,8 +1785,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("  if (!__Pyx_RefNanny)")
         code.putln("      Py_FatalError(\"failed to import 'refnanny' module\");")
         code.putln("}")
-        code.putln("__pyx_refnanny = __Pyx_RefNanny->SetupContext(\"%s\", __LINE__, __FILE__);"% header3)
         code.putln("#endif")
+        code.put_setup_refcount_context(header3)
+
+        env.use_utility_code(check_binary_version_utility_code)
+        code.putln("if ( __Pyx_check_binary_version() < 0) %s" % code.error_goto(self.pos))
 
         code.putln("%s = PyTuple_New(0); %s" % (Naming.empty_tuple, code.error_goto_if_null(Naming.empty_tuple, self.pos)));
         code.putln("%s = PyBytes_FromStringAndSize(\"\", 0); %s" % (Naming.empty_bytes, code.error_goto_if_null(Naming.empty_bytes, self.pos)));
@@ -1791,6 +1834,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("/*--- Global init code ---*/")
         self.generate_global_init_code(env, code)
 
+        code.putln("/*--- Variable export code ---*/")
+        self.generate_c_variable_export_code(env, code)
+
         code.putln("/*--- Function export code ---*/")
         self.generate_c_function_export_code(env, code)
 
@@ -1888,7 +1934,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
 
     def generate_main_method(self, env, code):
         module_is_main = "%s%s" % (Naming.module_is_main, self.full_module_name.replace('.', '__'))
-        code.globalstate.use_utility_code(main_method.specialize(module_name=env.module_name, module_is_main=module_is_main))
+        if Options.embed == "main":
+            wmain = "wmain"
+        else:
+            wmain = Options.embed
+        code.globalstate.use_utility_code(
+            main_method.specialize(
+                module_name = env.module_name,
+                module_is_main = module_is_main,
+                main_method = Options.embed,
+                wmain_method = wmain))
 
     def generate_pymoduledef_struct(self, env, code):
         if env.doc:
@@ -1969,6 +2024,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 if entry.type.is_pyobject and entry.used:
                     code.put_init_var_to_py_none(entry, nanny=False)
 
+    def generate_c_variable_export_code(self, env, code):
+        # Generate code to create PyCFunction wrappers for exported C functions.
+        for entry in env.var_entries:
+            if entry.api or entry.defined_in_pxd:
+                env.use_utility_code(voidptr_export_utility_code)
+                signature = entry.type.declaration_code("")
+                code.putln('if (__Pyx_ExportVoidPtr("%s", (void *)&%s, "%s") < 0) %s' % (
+                    entry.name,
+                    entry.cname,
+                    signature,
+                    code.error_goto(self.pos)))
+
     def generate_c_function_export_code(self, env, code):
         # Generate code to create PyCFunction wrappers for exported C functions.
         for entry in env.cfunc_entries:
@@ -2067,19 +2134,21 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         else:
             objstruct = "struct %s" % type.objstruct_cname
         module_name = type.module_name
+        condition = None
         if module_name not in ('__builtin__', 'builtins'):
             module_name = '"%s"' % module_name
         else:
             module_name = '__Pyx_BUILTIN_MODULE_NAME'
-        if type.name in self.py3_type_name_map:
-            code.putln("#if PY_MAJOR_VERSION >= 3")
-            code.putln('%s = __Pyx_ImportType(%s, "%s", sizeof(%s), 1); %s' % (
-                    type.typeptr_cname,
-                    module_name,
-                    self.py3_type_name_map[type.name],
-                    objstruct,
-                    error_code))
-            code.putln("#else")
+            if type.name in Code.non_portable_builtins_map:
+                condition, replacement = Code.non_portable_builtins_map[entry.name]
+                code.putln("#if %s" % condition)
+                code.putln('%s = __Pyx_ImportType(%s, "%s", sizeof(%s), 1); %s' % (
+                        type.typeptr_cname,
+                        module_name,
+                        replacement,
+                        objstruct,
+                        error_code))
+                code.putln("#else")
         code.putln('%s = __Pyx_ImportType(%s, "%s", sizeof(%s), %i); %s' % (
                 type.typeptr_cname,
                 module_name,
@@ -2087,7 +2156,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 objstruct,
                 not type.is_external or type.is_subclassed,
                 error_code))
-        if type.name in self.py3_type_name_map:
+        if condition:
             code.putln("#endif")
 
     def generate_type_ready_code(self, env, entry, code):
@@ -2312,6 +2381,45 @@ bad:
 
 #------------------------------------------------------------------------------------
 
+voidptr_export_utility_code = UtilityCode(
+proto = """
+static int __Pyx_ExportVoidPtr(const char *name, void *p, const char *sig); /*proto*/
+""",
+impl = r"""
+static int __Pyx_ExportVoidPtr(const char *name, void *p, const char *sig) {
+    PyObject *d = 0;
+    PyObject *cobj = 0;
+
+    d = PyObject_GetAttrString(%(MODULE)s, (char *)"%(API)s");
+    if (!d) {
+        PyErr_Clear();
+        d = PyDict_New();
+        if (!d)
+            goto bad;
+        Py_INCREF(d);
+        if (PyModule_AddObject(%(MODULE)s, (char *)"%(API)s", d) < 0)
+            goto bad;
+    }
+#if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0)
+    cobj = PyCapsule_New(p, sig, 0);
+#else
+    cobj = PyCObject_FromVoidPtrAndDesc(p, (void *)sig, 0);
+#endif
+    if (!cobj)
+        goto bad;
+    if (PyDict_SetItemString(d, name, cobj) < 0)
+        goto bad;
+    Py_DECREF(cobj);
+    Py_DECREF(d);
+    return 0;
+bad:
+    Py_XDECREF(cobj);
+    Py_XDECREF(d);
+    return -1;
+}
+""" % {'MODULE': Naming.module_cname, 'API': Naming.api_name}
+)
+
 function_export_utility_code = UtilityCode(
 proto = """
 static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig); /*proto*/
@@ -2356,6 +2464,62 @@ bad:
 """ % {'MODULE': Naming.module_cname, 'API': Naming.api_name}
 )
 
+voidptr_import_utility_code = UtilityCode(
+proto = """
+static int __Pyx_ImportVoidPtr(PyObject *module, const char *name, void **p, const char *sig); /*proto*/
+""",
+impl = """
+#ifndef __PYX_HAVE_RT_ImportVoidPtr
+#define __PYX_HAVE_RT_ImportVoidPtr
+static int __Pyx_ImportVoidPtr(PyObject *module, const char *name, void **p, const char *sig) {
+    PyObject *d = 0;
+    PyObject *cobj = 0;
+
+    d = PyObject_GetAttrString(module, (char *)"%(API)s");
+    if (!d)
+        goto bad;
+    cobj = PyDict_GetItemString(d, name);
+    if (!cobj) {
+        PyErr_Format(PyExc_ImportError,
+            "%%s does not export expected C variable %%s",
+                PyModule_GetName(module), name);
+        goto bad;
+    }
+#if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0)
+    if (!PyCapsule_IsValid(cobj, sig)) {
+        PyErr_Format(PyExc_TypeError,
+            "C variable %%s.%%s has wrong signature (expected %%s, got %%s)",
+             PyModule_GetName(module), name, sig, PyCapsule_GetName(cobj));
+        goto bad;
+    }
+    *p = PyCapsule_GetPointer(cobj, sig);
+#else
+    {const char *desc, *s1, *s2;
+    desc = (const char *)PyCObject_GetDesc(cobj);
+    if (!desc)
+        goto bad;
+    s1 = desc; s2 = sig;
+    while (*s1 != '\\0' && *s1 == *s2) { s1++; s2++; }
+    if (*s1 != *s2) {
+        PyErr_Format(PyExc_TypeError,
+            "C variable %%s.%%s has wrong signature (expected %%s, got %%s)",
+             PyModule_GetName(module), name, sig, desc);
+        goto bad;
+    }
+    *p = PyCObject_AsVoidPtr(cobj);}
+#endif
+    if (!(*p))
+        goto bad;
+    Py_DECREF(d);
+    return 0;
+bad:
+    Py_XDECREF(d);
+    return -1;
+}
+#endif
+""" % dict(API = Naming.api_name)
+)
+
 function_import_utility_code = UtilityCode(
 proto = """
 static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (**f)(void), const char *sig); /*proto*/
@@ -2579,7 +2743,8 @@ bad:
 """ % {'IMPORT_STAR'     : Naming.import_star,
        'IMPORT_STAR_SET' : Naming.import_star_set }
 
-refnanny_utility_code = UtilityCode(proto="""
+refnanny_utility_code = UtilityCode(
+proto="""
 #ifndef CYTHON_REFNANNY
   #define CYTHON_REFNANNY 0
 #endif
@@ -2594,43 +2759,52 @@ refnanny_utility_code = UtilityCode(proto="""
     void (*FinishContext)(void**);
   } __Pyx_RefNannyAPIStruct;
   static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL;
-  static __Pyx_RefNannyAPIStruct * __Pyx_RefNannyImportAPI(const char *modname) {
-    PyObject *m = NULL, *p = NULL;
-    void *r = NULL;
-    m = PyImport_ImportModule((char *)modname);
-    if (!m) goto end;
-    p = PyObject_GetAttrString(m, (char *)\"RefNannyAPI\");
-    if (!p) goto end;
-    r = PyLong_AsVoidPtr(p);
-  end:
-    Py_XDECREF(p);
-    Py_XDECREF(m);
-    return (__Pyx_RefNannyAPIStruct *)r;
-  }
-  #define __Pyx_RefNannyDeclareContext void *__pyx_refnanny;
+  static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); /*proto*/
+  #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL;
   #define __Pyx_RefNannySetupContext(name) \
           __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__)
   #define __Pyx_RefNannyFinishContext() \
           __Pyx_RefNanny->FinishContext(&__pyx_refnanny)
-  #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
-  #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
-  #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_INCREF(r)  __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_DECREF(r)  __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
+  #define __Pyx_GOTREF(r)  __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
   #define __Pyx_GIVEREF(r) __Pyx_RefNanny->GIVEREF(__pyx_refnanny, (PyObject *)(r), __LINE__)
-  #define __Pyx_XDECREF(r) do { if((r) != NULL) {__Pyx_DECREF(r);} } while(0)
+  #define __Pyx_XINCREF(r)  do { if((r) != NULL) {__Pyx_INCREF(r); }} while(0)
+  #define __Pyx_XDECREF(r)  do { if((r) != NULL) {__Pyx_DECREF(r); }} while(0)
+  #define __Pyx_XGOTREF(r)  do { if((r) != NULL) {__Pyx_GOTREF(r); }} while(0)
+  #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0)
 #else
-  #define __Pyx_RefNannyDeclareContext
+  #define __Pyx_RefNannyDeclarations
   #define __Pyx_RefNannySetupContext(name)
   #define __Pyx_RefNannyFinishContext()
   #define __Pyx_INCREF(r) Py_INCREF(r)
   #define __Pyx_DECREF(r) Py_DECREF(r)
   #define __Pyx_GOTREF(r)
   #define __Pyx_GIVEREF(r)
+  #define __Pyx_XINCREF(r) Py_XINCREF(r)
   #define __Pyx_XDECREF(r) Py_XDECREF(r)
+  #define __Pyx_XGOTREF(r)
+  #define __Pyx_XGIVEREF(r)
 #endif /* CYTHON_REFNANNY */
-#define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);} } while(0)
-#define __Pyx_XGOTREF(r) do { if((r) != NULL) {__Pyx_GOTREF(r);} } while(0)
-""")
-
+""",
+impl="""
+#if CYTHON_REFNANNY
+static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) {
+    PyObject *m = NULL, *p = NULL;
+    void *r = NULL;
+    m = PyImport_ImportModule((char *)modname);
+    if (!m) goto end;
+    p = PyObject_GetAttrString(m, (char *)\"RefNannyAPI\");
+    if (!p) goto end;
+    r = PyLong_AsVoidPtr(p);
+end:
+    Py_XDECREF(p);
+    Py_XDECREF(m);
+    return (__Pyx_RefNannyAPIStruct *)r;
+}
+#endif /* CYTHON_REFNANNY */
+""",
+)
 
 main_method = UtilityCode(
 impl = """
@@ -2639,14 +2813,12 @@ impl = """
 #endif
 
 #if PY_MAJOR_VERSION < 3
-int main(int argc, char** argv) {
+int %(main_method)s(int argc, char** argv) {
 #elif defined(WIN32) || defined(MS_WINDOWS)
-int wmain(int argc, wchar_t **argv) {
+int %(wmain_method)s(int argc, wchar_t **argv) {
 #else
 static int __Pyx_main(int argc, wchar_t **argv) {
 #endif
-    int r = 0;
-    PyObject* m = NULL;
     /* 754 requires that FP exceptions run in "no stop" mode by default,
      * and until C vendors implement C99's ways to control FP exceptions,
      * Python requires non-stop mode.  Alas, some platforms enable FP
@@ -2658,25 +2830,30 @@ static int __Pyx_main(int argc, wchar_t **argv) {
     m = fpgetmask();
     fpsetmask(m & ~FP_X_OFL);
 #endif
-    Py_SetProgramName(argv[0]);
+    if (argc && argv)
+        Py_SetProgramName(argv[0]);
     Py_Initialize();
-    PySys_SetArgv(argc, argv);
-    %(module_is_main)s = 1;
-#if PY_MAJOR_VERSION < 3
-        init%(module_name)s();
-#else
-        m = PyInit_%(module_name)s();
-#endif
-    if (PyErr_Occurred() != NULL) {
-        r = 1;
-        PyErr_Print(); /* This exits with the right code if SystemExit. */
-#if PY_MAJOR_VERSION < 3
-        if (Py_FlushLine()) PyErr_Clear();
-#endif
+    if (argc && argv)
+        PySys_SetArgv(argc, argv);
+    { /* init module '%(module_name)s' as '__main__' */
+      PyObject* m = NULL;
+      %(module_is_main)s = 1;
+      #if PY_MAJOR_VERSION < 3
+          init%(module_name)s();
+      #else
+          m = PyInit_%(module_name)s();
+      #endif
+      if (PyErr_Occurred()) {
+          PyErr_Print(); /* This exits with the right code if SystemExit. */
+          #if PY_MAJOR_VERSION < 3
+          if (Py_FlushLine()) PyErr_Clear();
+          #endif
+          return 1;
+      }
+      Py_XDECREF(m);
     }
-    Py_XDECREF(m);
     Py_Finalize();
-    return r;
+    return 0;
 }
 
 
@@ -2787,33 +2964,38 @@ oom:
 }
 
 int
-main(int argc, char **argv)
+%(main_method)s(int argc, char **argv)
 {
-       wchar_t **argv_copy = (wchar_t **)malloc(sizeof(wchar_t*)*argc);
-       /* We need a second copies, as Python might modify the first one. */
-       wchar_t **argv_copy2 = (wchar_t **)malloc(sizeof(wchar_t*)*argc);
-       int i, res;
-       char *oldloc;
-       if (!argv_copy || !argv_copy2) {
-               fprintf(stderr, "out of memory\\n");
-               return 1;
-       }
-       oldloc = strdup(setlocale(LC_ALL, NULL));
-       setlocale(LC_ALL, "");
-       for (i = 0; i < argc; i++) {
-               argv_copy2[i] = argv_copy[i] = __Pyx_char2wchar(argv[i]);
-               if (!argv_copy[i])
-                       return 1;
-       }
-       setlocale(LC_ALL, oldloc);
-       free(oldloc);
-       res = __Pyx_main(argc, argv_copy);
-       for (i = 0; i < argc; i++) {
-               free(argv_copy2[i]);
-       }
-       free(argv_copy);
-       free(argv_copy2);
-       return res;
+    if (!argc) {
+        return __Pyx_main(0, NULL);
+    }
+    else {
+        wchar_t **argv_copy = (wchar_t **)malloc(sizeof(wchar_t*)*argc);
+        /* We need a second copies, as Python might modify the first one. */
+        wchar_t **argv_copy2 = (wchar_t **)malloc(sizeof(wchar_t*)*argc);
+        int i, res;
+        char *oldloc;
+        if (!argv_copy || !argv_copy2) {
+            fprintf(stderr, "out of memory\\n");
+            return 1;
+        }
+        oldloc = strdup(setlocale(LC_ALL, NULL));
+        setlocale(LC_ALL, "");
+        for (i = 0; i < argc; i++) {
+            argv_copy2[i] = argv_copy[i] = __Pyx_char2wchar(argv[i]);
+            if (!argv_copy[i])
+                return 1;
+        }
+        setlocale(LC_ALL, oldloc);
+        free(oldloc);
+        res = __Pyx_main(argc, argv_copy);
+        for (i = 0; i < argc; i++) {
+            free(argv_copy2[i]);
+        }
+        free(argv_copy);
+        free(argv_copy2);
+        return res;
+    }
 }
 #endif
 """)
@@ -2825,3 +3007,26 @@ packed_struct_utility_code = UtilityCode(proto="""
 #define __Pyx_PACKED
 #endif
 """, impl="", proto_block='utility_code_proto_before_types')
+
+check_binary_version_utility_code = UtilityCode(proto="""
+static int __Pyx_check_binary_version(void);
+""", impl="""
+static int __Pyx_check_binary_version(void) {
+    char ctversion[4], rtversion[4];
+    PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION);
+    PyOS_snprintf(rtversion, 4, "%s", Py_GetVersion());
+    if (ctversion[0] != rtversion[0] || ctversion[2] != rtversion[2]) {
+        char message[200];
+        PyOS_snprintf(message, sizeof(message),
+                      "compiletime version %s of module '%.100s' "
+                      "does not match runtime version %s",
+                      ctversion, __Pyx_MODULE_NAME, rtversion);
+        #if PY_VERSION_HEX < 0x02050000
+        return PyErr_Warn(NULL, message);
+        #else
+        return PyErr_WarnEx(NULL, message, 1);
+        #endif
+    }
+    return 0;
+}
+""")