Commit 81f9a985 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Fix for#257

parent e6fe63d9
...@@ -432,7 +432,7 @@ def use_empty_bufstruct_code(env, max_ndim): ...@@ -432,7 +432,7 @@ def use_empty_bufstruct_code(env, max_ndim):
Py_ssize_t __Pyx_zeros[] = {%s}; Py_ssize_t __Pyx_zeros[] = {%s};
Py_ssize_t __Pyx_minusones[] = {%s}; Py_ssize_t __Pyx_minusones[] = {%s};
""") % (", ".join(["0"] * max_ndim), ", ".join(["-1"] * max_ndim)) """) % (", ".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): def buf_lookup_full_code(proto, defin, name, nd):
...@@ -494,7 +494,6 @@ def use_py2_buffer_functions(env): ...@@ -494,7 +494,6 @@ def use_py2_buffer_functions(env):
# Emulation of PyObject_GetBuffer and PyBuffer_Release for Python 2. # Emulation of PyObject_GetBuffer and PyBuffer_Release for Python 2.
# For >= 2.6 we do double mode -- use the new buffer interface on objects # For >= 2.6 we do double mode -- use the new buffer interface on objects
# which has the right tp_flags set, but emulation otherwise. # which has the right tp_flags set, but emulation otherwise.
codename = "PyObject_GetBuffer" # just a representative unique key
# Search all types for __getbuffer__ overloads # Search all types for __getbuffer__ overloads
types = [] types = []
...@@ -567,7 +566,7 @@ def use_py2_buffer_functions(env): ...@@ -567,7 +566,7 @@ def use_py2_buffer_functions(env):
#define __Pyx_GetBuffer PyObject_GetBuffer #define __Pyx_GetBuffer PyObject_GetBuffer
#define __Pyx_ReleaseBuffer PyBuffer_Release #define __Pyx_ReleaseBuffer PyBuffer_Release
#endif #endif
"""), impl = code), codename) """), impl = code))
def mangle_dtype_name(dtype): def mangle_dtype_name(dtype):
......
...@@ -18,9 +18,13 @@ import DebugFlags ...@@ -18,9 +18,13 @@ import DebugFlags
from Cython.Utils import none_or_sub from Cython.Utils import none_or_sub
# a simple class that simplifies the usage of utility code
class UtilityCode(object): 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): def __init__(self, proto=None, impl=None, init=None, cleanup=None, requires=None):
self.proto = proto self.proto = proto
self.impl = impl self.impl = impl
......
...@@ -1236,6 +1236,44 @@ class CFuncTypeArg(object): ...@@ -1236,6 +1236,44 @@ class CFuncTypeArg(object):
def declaration_code(self, for_display = 0): def declaration_code(self, for_display = 0):
return self.type.declaration_code(self.cname, for_display) 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): class CStructOrUnionType(CType):
# name string # name string
...@@ -1264,39 +1302,18 @@ class CStructOrUnionType(CType): ...@@ -1264,39 +1302,18 @@ class CStructOrUnionType(CType):
def create_to_py_utility_code(self, env): def create_to_py_utility_code(self, env):
if env.outer_scope is None: if env.outer_scope is None:
return False return False
if self._convert_code is False: return # tri-state-ish
if self._convert_code is None: 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: for member in self.scope.var_entries:
if member.type.to_py_function and member.type.create_to_py_utility_code(env): if not member.type.to_py_function or not 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:
self.to_py_function = None self.to_py_function = None
self._convert_code = False
return 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) entry = env.lookup(self.name)
if entry.visibility != 'extern': forward_decl = (entry.visibility != 'extern')
proto = self.declaration_code('') + ';\n' + proto self._convert_code = StructUtilityCode(self, forward_decl)
self._convert_code = UtilityCode(proto=proto, impl=code.buffer.getvalue())
env.use_utility_code(self._convert_code) env.use_utility_code(self._convert_code)
return True return True
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment