Fix for#257
authorDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Thu, 21 May 2009 20:33:33 +0000 (22:33 +0200)
committerDag Sverre Seljebotn <dagss@student.matnat.uio.no>
Thu, 21 May 2009 20:33:33 +0000 (22:33 +0200)
Cython/Compiler/Buffer.py
Cython/Compiler/Code.py
Cython/Compiler/PyrexTypes.py

index 91fd6adb1217a8aa64f38d15b72fdeb6994fff28..bfcedc9cc2fc567dcfb6afa27e108f1dfb56ea42 100644 (file)
@@ -432,7 +432,7 @@ def use_empty_bufstruct_code(env, max_ndim):
         Py_ssize_t __Pyx_zeros[] = {%s};
         Py_ssize_t __Pyx_minusones[] = {%s};
     """) % (", ".join(["0"] * max_ndim), ", ".join(["-1"] * max_ndim))
-    env.use_utility_code(UtilityCode(proto=code), "empty_bufstruct_code")
+    env.use_utility_code(UtilityCode(proto=code))
 
 
 def buf_lookup_full_code(proto, defin, name, nd):
@@ -494,7 +494,6 @@ def use_py2_buffer_functions(env):
     # Emulation of PyObject_GetBuffer and PyBuffer_Release for Python 2.
     # For >= 2.6 we do double mode -- use the new buffer interface on objects
     # which has the right tp_flags set, but emulation otherwise.
-    codename = "PyObject_GetBuffer" # just a representative unique key
 
     # Search all types for __getbuffer__ overloads
     types = []
@@ -567,7 +566,7 @@ def use_py2_buffer_functions(env):
         #define __Pyx_GetBuffer PyObject_GetBuffer
         #define __Pyx_ReleaseBuffer PyBuffer_Release
         #endif
-    """), impl = code), codename)
+    """), impl = code))
 
 
 def mangle_dtype_name(dtype):
index 8ac936105d0a9634eb46d7f85951094aab38dce8..a54372cce598b0c9565b5308071b3d920f89b124 100644 (file)
@@ -18,9 +18,13 @@ import DebugFlags
 
 from Cython.Utils import none_or_sub
 
-# a simple class that simplifies the usage of utility code
-
 class UtilityCode(object):
+    # Stores utility code to add during code generation.
+    #
+    # See GlobalState.put_utility_code.
+    #
+    # hashes/equals by instance
+    
     def __init__(self, proto=None, impl=None, init=None, cleanup=None, requires=None):
         self.proto = proto
         self.impl = impl
index 682bc28ee570c773e1f34a572b70dc3f297a5665..7a0780f9346a1f000b3a1a65761eec26c0e75db9 100644 (file)
@@ -1236,6 +1236,44 @@ class CFuncTypeArg(object):
     def declaration_code(self, for_display = 0):
         return self.type.declaration_code(self.cname, for_display)
 
+class StructUtilityCode(object):
+    def __init__(self, type, forward_decl):
+        self.type = type
+        self.header = "static PyObject* %s(%s)" % (type.to_py_function, type.declaration_code('s'))
+        self.forward_decl = forward_decl
+
+    def __eq__(self, other):
+        return isinstance(other, StructUtilityCode) and self.header == other.header
+    def __hash__(self):
+        return hash(self.header)
+    
+    def put_code(self, output):
+        code = output['utility_code_def']
+        proto = output['utility_code_proto']
+        
+        code.putln("%s {" % self.header)
+        code.putln("PyObject* res;")
+        code.putln("PyObject* member;")
+        code.putln("res = PyDict_New(); if (res == NULL) return NULL;")
+        for member in self.type.scope.var_entries:
+            nameconst_cname = code.get_py_string_const(member.name, identifier=True)
+            code.putln("member = %s(s.%s); if (member == NULL) goto bad;" % (
+                member.type.to_py_function, member.cname))
+            code.putln("if (PyDict_SetItem(res, %s, member) < 0) goto bad;" % nameconst_cname)
+            code.putln("Py_DECREF(member);")
+        code.putln("return res;")
+        code.putln("bad:")
+        code.putln("Py_XDECREF(member);")
+        code.putln("Py_DECREF(res);")
+        code.putln("return NULL;")
+        code.putln("}")
+
+        # This is a bit of a hack, we need a forward declaration
+        # due to the way things are ordered in the module...
+        if self.forward_decl:
+            proto.putln(self.type.declaration_code('') + ';')
+        proto.putln(self.header + ";")
+        
 
 class CStructOrUnionType(CType):
     #  name          string
@@ -1264,39 +1302,18 @@ class CStructOrUnionType(CType):
     def create_to_py_utility_code(self, env):
         if env.outer_scope is None:
             return False
+
+        if self._convert_code is False: return # tri-state-ish
+
         if self._convert_code is None:
-            import Code
-            code = Code.CCodeWriter()
-            Code.GlobalState(code)
-            header = "static PyObject* %s(%s)" % (self.to_py_function, self.declaration_code('s'))
-            code.putln("%s {" % header)
-            code.putln("PyObject* res;")
-            code.putln("PyObject* member;")
-            code.putln("res = PyDict_New(); if (res == NULL) return NULL;")
             for member in self.scope.var_entries:
-                if member.type.to_py_function and member.type.create_to_py_utility_code(env):
-                    interned_name = env.get_string_const(member.name, identifier=True)
-                    env.add_py_string(interned_name)
-                    code.putln("member = %s(s.%s); if (member == NULL) goto bad;" % (
-                                                member.type.to_py_function, member.cname))
-                    code.putln("if (PyDict_SetItem(res, %s, member) < 0) goto bad;" % interned_name.pystring_cname)
-                    code.putln("Py_DECREF(member);")
-                else:
+                if not member.type.to_py_function or not member.type.create_to_py_utility_code(env):
                     self.to_py_function = None
+                    self._convert_code = False
                     return False
-            code.putln("return res;")
-            code.putln("bad:")
-            code.putln("Py_XDECREF(member);")
-            code.putln("Py_DECREF(res);")
-            code.putln("return NULL;")
-            code.putln("}")
-            proto = header + ";"
-            # This is a bit of a hack, we need a forward declaration
-            # due to the way things are ordered in the module...
             entry = env.lookup(self.name)
-            if entry.visibility != 'extern':
-                proto = self.declaration_code('') + ';\n' + proto
-            self._convert_code = UtilityCode(proto=proto, impl=code.buffer.getvalue())
+            forward_decl = (entry.visibility != 'extern')
+            self._convert_code = StructUtilityCode(self, forward_decl)
         
         env.use_utility_code(self._convert_code)
         return True