Merged pull request #12 from bhy/T423.
[cython.git] / Cython / Compiler / ModuleNode.py
index d46d605e9b8b7a0995407914c3b4fb46c3b61fdb..738d13600b27da6a71e8cfed42d2c659d45afc13 100644 (file)
@@ -6,7 +6,7 @@ import cython
 from cython import set
 cython.declare(Naming=object, Options=object, PyrexTypes=object, TypeSlots=object,
                error=object, warning=object, py_object_type=object, UtilityCode=object,
-               escape_byte_string=object, EncodedString=object)
+               EncodedString=object)
 
 import os, time
 from PyrexTypes import CPtrType
@@ -26,7 +26,7 @@ from Errors import error, warning
 from PyrexTypes import py_object_type
 from Cython.Utils import open_new_file, replace_suffix
 from Code import UtilityCode
-from StringEncoding import escape_byte_string, EncodedString
+from StringEncoding import EncodedString
 
 
 def check_c_declarations_pxd(module_node):
@@ -51,7 +51,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
 
     child_attrs = ["body"]
     directives = None
-    
+
     def analyse_declarations(self, env):
         if Options.embed_pos_in_docstring:
             env.doc = EncodedString(u'File: %s (starting at line %s)' % Nodes.relative_position(self.pos))
@@ -62,7 +62,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             env.doc = self.doc
         env.directives = self.directives
         self.body.analyse_declarations(env)
-    
+
     def process_implementation(self, options, result):
         env = self.scope
         env.return_type = PyrexTypes.c_void_type
@@ -73,14 +73,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         self.generate_c_code(env, options, result)
         self.generate_h_code(env, options, result)
         self.generate_api_code(env, result)
-    
+
     def has_imported_c_functions(self):
         for module in self.referenced_modules:
             for entry in module.cfunc_entries:
                 if entry.defined_in_pxd:
                     return 1
         return 0
-    
+
     def generate_dep_file(self, env, result):
         modules = self.referenced_modules
         if len(modules) > 1 or env.included_files:
@@ -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,105 +114,122 @@ 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.copyto(open_new_file(result.h_file))
-    
+            h_code.putln("")
+            h_code.putln("#endif /* !%s */" % h_guard)
+
+            f = open_new_file(result.h_file)
+            try:
+                h_code.copyto(f)
+            finally:
+                f.close()
+
     def generate_public_declaration(self, entry, h_code, i_code):
         h_code.putln("%s %s;" % (
             Naming.extern_c_macro,
             entry.type.declaration_code(
                 entry.cname, dll_linkage = "DL_IMPORT")))
         if i_code:
-            i_code.putln("cdef extern %s" % 
+            i_code.putln("cdef extern %s" %
                 entry.type.declaration_code(entry.cname, pyrex = 1))
-    
+
     def api_name(self, env):
         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)
@@ -220,15 +239,20 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             h_code.putln("return -1;")
             h_code.putln("}")
             h_code.putln("")
-            h_code.putln("#endif")
-            
-            h_code.copyto(open_new_file(result.api_file))
-    
+            h_code.putln("#endif /* !%s */" % api_guard)
+
+            f = open_new_file(result.api_file)
+            try:
+                h_code.copyto(f)
+            finally:
+                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):
         i_code.putln("cdef extern class %s.%s:" % (
             type.module_name, type.name))
@@ -236,12 +260,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         var_entries = type.scope.var_entries
         if var_entries:
             for entry in var_entries:
-                i_code.putln("cdef %s" % 
+                i_code.putln("cdef %s" %
                     entry.type.declaration_code(entry.cname, pyrex = 1))
         else:
             i_code.putln("pass")
         i_code.dedent()
-    
+
     def generate_c_code(self, env, options, result):
         modules = self.referenced_modules
 
@@ -250,11 +274,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             rootwriter = Annotate.AnnotationCCodeWriter()
         else:
             emit_linenums = options.emit_linenums
-            rootwriter = Code.CCodeWriter(emit_linenums=emit_linenums)
+            rootwriter = Code.CCodeWriter(emit_linenums=emit_linenums, c_line_in_traceback=options.c_line_in_traceback)
         globalstate = Code.GlobalState(rootwriter, emit_linenums)
         globalstate.initialize_main_c_code()
         h_code = globalstate['h_code']
-        
+
         self.generate_module_preamble(env, modules, h_code)
 
         globalstate.module_pos = self.pos
@@ -287,22 +311,44 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         if Options.embed:
             self.generate_main_method(env, globalstate['main_method'])
         self.generate_filename_table(globalstate['filename_table'])
-        
+
         self.generate_declarations_for_modules(env, modules, globalstate)
         h_code.write('\n')
 
         for utilcode in env.utility_code_list:
             globalstate.use_utility_code(utilcode)
         globalstate.finalize_main_c_code()
-        
+
         f = open_new_file(result.c_file)
         rootwriter.copyto(f)
+        if options.gdb_debug:
+            self._serialize_lineno_map(env, rootwriter)
         f.close()
         result.c_file_generated = 1
         if Options.annotate or options.annotate:
             self.annotate(rootwriter)
             rootwriter.save_annotation(result.main_source_file, result.c_file)
-    
+
+    def _serialize_lineno_map(self, env, ccodewriter):
+        tb = env.context.gdb_debug_outputwriter
+        markers = ccodewriter.buffer.allmarkers()
+
+        d = {}
+        for c_lineno, cython_lineno in enumerate(markers):
+            if cython_lineno > 0:
+                d.setdefault(cython_lineno, []).append(c_lineno + 1)
+
+        tb.start('LineNumberMapping')
+        for cython_lineno, c_linenos in sorted(d.iteritems()):
+                attrs = {
+                    'c_linenos': ' '.join(map(str, c_linenos)),
+                    'cython_lineno': str(cython_lineno),
+                }
+                tb.start('LineNumber', attrs)
+                tb.end('LineNumber')
+        tb.end('LineNumberMapping')
+        tb.serialize()
+
     def find_referenced_modules(self, env, module_list, modules_seen):
         if env not in modules_seen:
             modules_seen[env] = 1
@@ -356,7 +402,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                     if type.is_extension_type and not entry.in_cinclude:
                         type = entry.type
                         vtabslot_dict[type.objstruct_cname] = entry
-                
+
         def vtabstruct_cname(entry_type):
             return entry_type.vtabstruct_cname
         vtab_list = self.sort_types_by_inheritance(
@@ -394,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)
 
@@ -425,7 +472,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("    #error Python headers needed to compile C extensions, please install development version of Python.")
         code.putln("#else")
         code.globalstate["end"].putln("#endif /* Py_PYTHON_H */")
-        
+
         code.put("""
 #include <stddef.h> /* For offsetof */
 #ifndef offsetof
@@ -547,14 +594,18 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
   #define PyBytes_Repr                 PyString_Repr
   #define PyBytes_Concat               PyString_Concat
   #define PyBytes_ConcatAndDel         PyString_ConcatAndDel
+#endif
+
+#if PY_VERSION_HEX < 0x02060000
   #define PySet_Check(obj)             PyObject_TypeCheck(obj, &PySet_Type)
   #define PyFrozenSet_Check(obj)       PyObject_TypeCheck(obj, &PyFrozenSet_Type)
 #endif
-
 #ifndef PySet_CheckExact
-#  define PySet_CheckExact(obj)          (Py_TYPE(obj) == &PySet_Type)
+  #define PySet_CheckExact(obj)        (Py_TYPE(obj) == &PySet_Type)
 #endif
 
+#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type)
+
 #if PY_MAJOR_VERSION >= 3
   #define PyIntObject                  PyLongObject
   #define PyInt_Type                   PyLong_Type
@@ -573,7 +624,16 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
 #endif
 
 #if PY_MAJOR_VERSION >= 3
-  #define PyBoolObject PyLongObject
+  #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
 
 """)
@@ -642,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("")
@@ -678,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):
@@ -692,7 +755,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 code.putln('#include %s' % byte_decoded_filenname)
             else:
                 code.putln('#include "%s"' % byte_decoded_filenname)
-    
+
     def generate_filename_table(self, code):
         code.putln("")
         code.putln("static const char *%s[] = {" % Naming.filetable_cname)
@@ -725,7 +788,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                     self.generate_enum_definition(entry, code)
                 elif type.is_extension_type:
                     self.generate_objstruct_definition(type, code)
-        
+
     def generate_gcc33_hack(self, env, code):
         # Workaround for spurious warning generation in gcc 3.3
         code.putln("")
@@ -739,14 +802,17 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                     tail = name
                 code.putln("typedef struct %s __pyx_gcc33_%s;" % (
                     name, tail))
-    
+
     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):
@@ -757,7 +823,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             header = "%s %s {" % (kind, name)
             footer = "};"
         return header, footer
-    
+
     def generate_struct_union_definition(self, entry, code):
         code.mark_pos(entry.pos)
         type = entry.type
@@ -770,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)")
@@ -801,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:
@@ -826,24 +890,25 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                     value_code += ","
                 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("DL_EXPORT(PyTypeObject) %s;" % name)
-                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)
         # Generate struct declaration for an extension type's vtable.
@@ -864,7 +929,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                         "%s;" % method_entry.type.declaration_code("(*%s)" % method_entry.name))
             code.putln(
                 "};")
-    
+
     def generate_exttype_vtabptr_declaration(self, entry, code):
         code.mark_pos(entry.pos)
         # Generate declaration of pointer to an extension type's vtable.
@@ -873,7 +938,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             code.putln("static struct %s *%s;" % (
                 type.vtabstruct_cname,
                 type.vtabptr_cname))
-    
+
     def generate_objstruct_definition(self, type, code):
         code.mark_pos(type.pos)
         # Generate object struct definition for an
@@ -882,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:
@@ -900,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.
@@ -912,40 +980,42 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("")
         for entry in env.c_class_entries:
             if definition or entry.defined_in_pxd:
-                code.putln("static PyTypeObject *%s = 0;" % 
+                code.putln("static PyTypeObject *%s = 0;" %
                     entry.type.typeptr_cname)
-        code.put_var_declarations(env.var_entries, static = 1, 
+        code.put_var_declarations(env.var_entries, static = 1,
             dll_linkage = "DL_EXPORT", definition = definition)
-    
+
     def generate_cfunction_predeclarations(self, env, code, definition):
         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
+                header = type.declaration_code(entry.cname,
+                                               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*/" % (
                     storage_class,
                     modifiers,
                     header))
-    
+
     def generate_typeobj_definitions(self, env, code):
         full_module_name = env.qualified_name
         for entry in env.c_class_entries:
@@ -984,7 +1054,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                     self.generate_method_table(scope, code)
                     self.generate_getset_table(scope, code)
                     self.generate_typeobj_definition(full_module_name, entry, code)
-    
+
     def generate_exttype_vtable(self, scope, code):
         # Generate the definition of an extension type's vtable.
         type = scope.parent_type
@@ -992,14 +1062,14 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             code.putln("static struct %s %s;" % (
                 type.vtabstruct_cname,
                 type.vtable_cname))
-        
+
     def generate_self_cast(self, scope, code):
         type = scope.parent_type
         code.putln(
             "%s = (%s)o;" % (
                 type.declaration_code("p"),
                 type.declaration_code("")))
-    
+
     def generate_new_function(self, scope, code):
         tp_slot = TypeSlots.ConstructorSlot("tp_new", '__new__')
         slot_func = scope.mangle_internal("tp_new")
@@ -1059,7 +1129,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             else:
                 cinit_args = "o, a, k"
             code.putln(
-                "if (%s(%s) < 0) {" % 
+                "if (%s(%s) < 0) {" %
                     (entry.func_cname, cinit_args))
             code.put_decref_clear("o", py_object_type, nanny=False);
             code.putln(
@@ -1068,7 +1138,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             "return o;")
         code.putln(
             "}")
-    
+
     def generate_dealloc_function(self, scope, code):
         tp_slot = TypeSlots.ConstructorSlot("tp_dealloc", '__dealloc__')
         slot_func = scope.mangle_internal("tp_dealloc")
@@ -1102,7 +1172,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                     "(*Py_TYPE(o)->tp_free)(o);")
         code.putln(
             "}")
-    
+
     def generate_usr_dealloc_call(self, scope, code):
         entry = scope.lookup_here("__dealloc__")
         if entry:
@@ -1115,7 +1185,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             code.putln(
                     "++Py_REFCNT(o);")
             code.putln(
-                    "%s(o);" % 
+                    "%s(o);" %
                         entry.func_cname)
             code.putln(
                     "if (PyErr_Occurred()) PyErr_WriteUnraisable(o);")
@@ -1125,7 +1195,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                     "PyErr_Restore(etype, eval, etb);")
             code.putln(
                 "}")
-    
+
     def generate_traverse_function(self, scope, code):
         tp_slot = TypeSlots.GCDependentSlot("tp_traverse")
         slot_func = scope.mangle_internal("tp_traverse")
@@ -1163,7 +1233,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             if entry.type.is_extension_type:
                 var_code = "((PyObject*)%s)" % var_code
             code.putln(
-                        "e = (*v)(%s, a); if (e) return e;" 
+                        "e = (*v)(%s, a); if (e) return e;"
                             % var_code)
             code.putln(
                     "}")
@@ -1171,7 +1241,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 "return 0;")
         code.putln(
             "}")
-    
+
     def generate_clear_function(self, scope, code):
         tp_slot = TypeSlots.GCDependentSlot("tp_clear")
         slot_func = scope.mangle_internal("tp_clear")
@@ -1199,13 +1269,16 @@ 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;")
         code.putln(
             "}")
-            
+
     def generate_getitem_int_function(self, scope, code):
         # This function is put into the sq_item slot when
         # a __getitem__ method is present. It converts its
@@ -1273,7 +1346,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 "}")
         code.putln(
             "}")
-    
+
     def generate_guarded_basetype_call(
             self, base_type, substructure, slot, args, code):
         if base_type:
@@ -1385,7 +1458,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             "return v;")
         code.putln(
             "}")
-    
+
     def generate_setattro_function(self, scope, code):
         # Setting and deleting an attribute are both done through
         # the setattro method, so we dispatch to user's __setattr__
@@ -1425,7 +1498,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 "}")
         code.putln(
             "}")
-    
+
     def generate_descr_get_function(self, scope, code):
         # The __get__ function of a descriptor object can be
         # called with NULL for the second or third arguments
@@ -1453,7 +1526,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             "return r;")
         code.putln(
             "}")
-    
+
     def generate_descr_set_function(self, scope, code):
         # Setting and deleting are both done through the __set__
         # method of a descriptor, so we dispatch to user's __set__
@@ -1494,10 +1567,10 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             code.putln(
                     "return -1;")
         code.putln(
-                "}")        
+                "}")
         code.putln(
             "}")
-    
+
     def generate_property_accessors(self, cclass_scope, code):
         for entry in cclass_scope.property_entries:
             property_scope = entry.scope
@@ -1505,7 +1578,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 self.generate_property_get_function(entry, code)
             if property_scope.defines_any(["__set__", "__del__"]):
                 self.generate_property_set_function(entry, code)
-    
+
     def generate_property_get_function(self, property_entry, code):
         property_scope = property_entry.scope
         property_entry.getter_cname = property_scope.parent_scope.mangle(
@@ -1520,7 +1593,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                     get_entry.func_cname)
         code.putln(
             "}")
-    
+
     def generate_property_set_function(self, property_entry, code):
         property_scope = property_entry.scope
         property_entry.setter_cname = property_scope.parent_scope.mangle(
@@ -1569,8 +1642,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         if entry.visibility == 'public':
             header = "DL_EXPORT(PyTypeObject) %s = {"
         else:
-            #header = "statichere PyTypeObject %s = {"
-            header = "PyTypeObject %s = {"
+            header = "static PyTypeObject %s = {"
         #code.putln(header % scope.parent_type.typeobj_cname)
         code.putln(header % type.typeobj_cname)
         code.putln(
@@ -1591,11 +1663,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             slot.generate(scope, code)
         code.putln(
             "};")
-    
+
     def generate_method_table(self, env, code):
         code.putln("")
         code.putln(
-            "static PyMethodDef %s[] = {" % 
+            "static PyMethodDef %s[] = {" %
                 env.method_table_cname)
         for entry in env.pyfunc_entries:
             code.put_pymethoddef(entry, ",")
@@ -1603,7 +1675,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 "{0, 0, 0, 0}")
         code.putln(
             "};")
-    
+
     def generate_getset_table(self, env, code):
         if env.property_entries:
             code.putln("")
@@ -1659,7 +1731,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                     code.putln("Py_INCREF(o);")
                     code.put_decref(entry.cname, entry.type, nanny=False)
                     code.putln("%s = %s;" % (
-                        entry.cname, 
+                        entry.cname,
                         PyrexTypes.typecast(entry.type, py_object_type, "o")))
                 elif entry.type.from_py_function:
                     rhs = "%s(o)" % entry.type.from_py_function
@@ -1704,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();")
@@ -1713,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)));
@@ -1759,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)
 
@@ -1775,7 +1853,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
 
         code.putln("/*--- Execution code ---*/")
         code.mark_pos(None)
-        
+
         self.body.generate_execution_code(code)
 
         if Options.generate_cleanup_code:
@@ -1813,7 +1891,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         if not Options.generate_cleanup_code:
             return
         code.globalstate.use_utility_code(register_cleanup_utility_code)
-        code.putln('static PyObject *%s(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED PyObject *unused) {' % 
+        code.putln('static PyObject *%s(CYTHON_UNUSED PyObject *self, CYTHON_UNUSED PyObject *unused) {' %
                    Naming.cleanup_cname)
         if Options.generate_cleanup_code >= 2:
             code.putln("/*--- Global cleanup code ---*/")
@@ -1856,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:
@@ -1888,9 +1975,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         code.putln("#if PY_MAJOR_VERSION < 3")
         code.putln(
             '%s = Py_InitModule4(__Pyx_NAMESTR("%s"), %s, %s, 0, PYTHON_API_VERSION);' % (
-                env.module_cname, 
-                env.module_name, 
-                env.method_table_cname, 
+                env.module_cname,
+                env.module_name,
+                env.method_table_cname,
                 doc))
         code.putln("#else")
         code.putln(
@@ -1922,7 +2009,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         if Options.pre_import is not None:
             code.putln(
                 '%s = PyImport_AddModule(__Pyx_NAMESTR("%s"));' % (
-                    Naming.preimport_cname, 
+                    Naming.preimport_cname,
                     Options.pre_import))
             code.putln(
                 "if (!%s) %s;" % (
@@ -1937,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:
@@ -1946,9 +2045,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                 code.putln('if (__Pyx_ExportFunction("%s", (void (*)(void))%s, "%s") < 0) %s' % (
                     entry.name,
                     entry.cname,
-                    signature, 
+                    signature,
                     code.error_goto(self.pos)))
-    
+
     def generate_type_import_code_for_module(self, module, env, code):
         # Generate type import code for all exported extension types in
         # an imported module.
@@ -1956,7 +2055,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         for entry in module.c_class_entries:
             if entry.defined_in_pxd:
                 self.generate_type_import_code(env, entry.type, entry.pos, code)
-    
+
     def generate_c_function_import_code_for_module(self, module, env, code):
         # Generate import code for all exported C functions in a cimported module.
         entries = []
@@ -1982,7 +2081,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                         entry.type.signature_string(),
                         code.error_goto(self.pos)))
             code.putln("Py_DECREF(%s); %s = 0;" % (temp, temp))
-    
+
     def generate_type_init_code(self, env, code):
         # Generate type import code for extern extension types
         # and type ready code for non-extern ones.
@@ -2000,11 +2099,11 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
         if base_type and base_type.module_name != env.qualified_name \
                and not base_type.is_builtin_type:
             self.generate_type_import_code(env, base_type, self.pos, code)
-    
+
     def use_type_import_utility_code(self, env):
         env.use_utility_code(type_import_utility_code)
         env.use_utility_code(import_module_utility_code)
-    
+
     def generate_type_import_code(self, env, type, pos, code):
         # If not already done, generate code to import the typeobject of an
         # extension type defined in another module, and extract its C method
@@ -2019,12 +2118,12 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                                        code.error_goto_if_null(type.typeptr_cname, pos))
         self.use_type_import_utility_code(env)
         if type.vtabptr_cname:
-            code.putln(
-                "if (__Pyx_GetVtable(%s->tp_dict, &%s) < 0) %s" % (
-                    type.typeptr_cname,
-                    type.vtabptr_cname,
-                    code.error_goto(pos)))
             env.use_utility_code(Nodes.get_vtable_utility_code)
+            code.putln("%s = (struct %s*)__Pyx_GetVtable(%s->tp_dict); %s" % (
+                type.vtabptr_cname,
+                type.vtabstruct_cname,
+                type.typeptr_cname,
+                code.error_goto_if_null(type.vtabptr_cname, pos)))
         env.types_imported[type] = 1
 
     py3_type_name_map = {'str' : 'bytes', 'unicode' : 'str'}
@@ -2035,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,
@@ -2055,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):
@@ -2072,29 +2173,29 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                     "if (PyType_Ready(&%s) < 0) %s" % (
                         typeobj_cname,
                         code.error_goto(entry.pos)))
-                # Fix special method docstrings. This is a bit of a hack, but 
+                # Fix special method docstrings. This is a bit of a hack, but
                 # unless we let PyType_Ready create the slot wrappers we have
-                # a significant performance hit. (See trac #561.) 
+                # a significant performance hit. (See trac #561.)
                 for func in entry.type.scope.pyfunc_entries:
                     if func.is_special and Options.docstrings and func.wrapperbase_cname:
-                        code.putln("{");
+                        code.putln("{")
                         code.putln(
                             'PyObject *wrapper = __Pyx_GetAttrString((PyObject *)&%s, "%s"); %s' % (
                                 typeobj_cname,
                                 func.name,
-                                code.error_goto_if_null('wrapper', entry.pos)));
+                                code.error_goto_if_null('wrapper', entry.pos)))
                         code.putln(
-                            "if (Py_TYPE(wrapper) == &PyWrapperDescr_Type) {");
+                            "if (Py_TYPE(wrapper) == &PyWrapperDescr_Type) {")
                         code.putln(
                             "%s = *((PyWrapperDescrObject *)wrapper)->d_base;" % (
-                                func.wrapperbase_cname));
+                                func.wrapperbase_cname))
                         code.putln(
-                            "%s.doc = %s;" % (func.wrapperbase_cname, func.doc_cname));
+                            "%s.doc = %s;" % (func.wrapperbase_cname, func.doc_cname))
                         code.putln(
                             "((PyWrapperDescrObject *)wrapper)->d_base = &%s;" % (
-                                func.wrapperbase_cname));
-                        code.putln("}");
-                        code.putln("}");
+                                func.wrapperbase_cname))
+                        code.putln("}")
+                        code.putln("}")
                 if type.vtable_cname:
                     code.putln(
                         "if (__Pyx_SetVtable(%s.tp_dict, %s) < 0) %s" % (
@@ -2127,7 +2228,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                             weakref_entry.cname))
                     else:
                         error(weakref_entry.pos, "__weakref__ slot must be of type 'object'")
-    
+
     def generate_exttype_vtable_init_code(self, entry, code):
         # Generate code to initialise the C method table of an
         # extension type.
@@ -2156,7 +2257,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
                             meth_entry.cname,
                             cast,
                             meth_entry.func_cname))
-    
+
     def generate_typeptr_assignment_code(self, entry, code):
         # Generate code to initialise the typeptr of an extension
         # type defined in this module to point to its type object.
@@ -2165,7 +2266,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
             code.putln(
                 "%s = &%s;" % (
                     type.typeptr_cname, type.typeobj_cname))
-    
+
 #------------------------------------------------------------------------------------
 #
 #  Runtime support code
@@ -2248,13 +2349,13 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
     if (!result)
         goto bad;
     if (!PyType_Check(result)) {
-        PyErr_Format(PyExc_TypeError, 
+        PyErr_Format(PyExc_TypeError,
             "%s.%s is not a type object",
             module_name, class_name);
         goto bad;
     }
     if (!strict && ((PyTypeObject *)result)->tp_basicsize > size) {
-        PyOS_snprintf(warning, sizeof(warning), 
+        PyOS_snprintf(warning, sizeof(warning),
             "%s.%s size changed, may indicate binary incompatibility",
             module_name, class_name);
         #if PY_VERSION_HEX < 0x02050000
@@ -2264,7 +2365,7 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
         #endif
     }
     else if (((PyTypeObject *)result)->tp_basicsize != size) {
-        PyErr_Format(PyExc_ValueError, 
+        PyErr_Format(PyExc_ValueError,
             "%s.%s has the wrong size, try recompiling",
             module_name, class_name);
         goto bad;
@@ -2280,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*/
@@ -2324,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*/
@@ -2395,8 +2591,8 @@ static PyMethodDef cleanup_def = {__Pyx_NAMESTR("__cleanup"), (PyCFunction)&%(mo
 """ % {'module_cleanup': Naming.cleanup_cname},
 impl = """
 static int __Pyx_RegisterCleanup(void) {
-    /* Don't use Py_AtExit because that has a 32-call limit 
-     * and is called after python finalization. 
+    /* Don't use Py_AtExit because that has a 32-call limit
+     * and is called after python finalization.
      */
 
     PyObject *cleanup_func = 0;
@@ -2405,7 +2601,7 @@ static int __Pyx_RegisterCleanup(void) {
     PyObject *args = 0;
     PyObject *res = 0;
     int ret = -1;
-    
+
     cleanup_func = PyCFunction_New(&cleanup_def, 0);
     args = PyTuple_New(1);
     if (!cleanup_func || !args)
@@ -2514,11 +2710,11 @@ static int %(IMPORT_STAR)s(PyObject* m) {
 #endif
     PyObject *name;
     PyObject *item;
-    
+
     locals = PyDict_New();              if (!locals) goto bad;
     if (__Pyx_import_all_from(locals, m) < 0) goto bad;
     list = PyDict_Items(locals);        if (!list) goto bad;
-    
+
     for(i=0; i<PyList_GET_SIZE(list); i++) {
         name = PyTuple_GET_ITEM(PyList_GET_ITEM(list, i), 0);
         item = PyTuple_GET_ITEM(PyList_GET_ITEM(list, i), 1);
@@ -2535,7 +2731,7 @@ static int %(IMPORT_STAR)s(PyObject* m) {
 #endif
     }
     ret = 0;
-    
+
 bad:
     Py_XDECREF(locals);
     Py_XDECREF(list);
@@ -2546,8 +2742,9 @@ 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
@@ -2562,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 = """
@@ -2607,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
@@ -2626,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;
 }
 
 
@@ -2755,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
 """)
@@ -2793,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;
+}
+""")