if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric:
error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
if to_py and not from_py:
- if self.operand.type.to_py_function:
+ if (self.operand.type.to_py_function and
+ self.operand.type.create_convert_utility_code(env)):
self.result_ctype = py_object_type
self.operand = self.operand.coerce_to_pyobject(env)
else:
self.type = py_object_type
self.gil_check(env)
self.is_temp = 1
- if not arg.type.to_py_function:
+ if not arg.type.to_py_function or not arg.type.create_convert_utility_code(env):
error(arg.pos,
"Cannot convert '%s' to Python object" % arg.type)
-
+
gil_message = "Converting to Python object"
def analyse_types(self, env):
vtabptr_prefix = pyrex_prefix + "vtabptr_"
vtabstruct_prefix = pyrex_prefix + "vtabstruct_"
opt_arg_prefix = pyrex_prefix + "opt_args_"
+convert_func_prefix = pyrex_prefix + "convert_"
args_cname = pyrex_prefix + "args"
pykwdlist_cname = pyrex_prefix + "pyargnames"
from_py_function = None
exception_value = None
exception_check = 1
-
+
+ def create_convert_utility_code(self, env):
+ return True
+
def error_condition(self, result_code):
conds = []
if self.is_string:
self.scope = scope
self.typedef_flag = typedef_flag
self.is_struct = kind == 'struct'
+ if self.is_struct:
+ self.to_py_function = "%s_to_py_%s" % (Naming.convert_func_prefix, self.cname)
+ self.exception_check = True
+ self._convert_code = None
+
+ def create_convert_utility_code(self, env):
+ if env.outer_scope is None:
+ return False
+ if self._convert_code is None:
+ import Code
+ code = Code.CCodeWriter()
+ 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_convert_utility_code(env):
+ 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;" % member.py_name.pystring_cname)
+ code.putln("Py_DECREF(member);")
+ else:
+ self.to_py_function = None
+ 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("}")
+ self._convert_code = self.declaration_code('') + ';\n' + header+";", code.buffer.getvalue()
+
+ env.use_utility_code(self._convert_code)
+ return True
def __repr__(self):
return "<CStructOrUnionType %s %s%s>" % (self.name, self.cname,
from_py_function = "dummy"
typestring = None
+ def create_convert_utility_code(self, env):
+ return True
+
def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0):
return "<error>"
self.type_entries.append(entry)
if not scope and not entry.type.scope:
self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
+ if scope and self.outer_scope:
+ scope.module_scope = self
return entry
def check_previous_typedef_flag(self, entry, typedef_flag, pos):
return "%s%s%d" % (Naming.const_prefix, prefix, n)
def use_utility_code(self, new_code, name=None):
- self.utility_code_list.append((new_code, name))
+ if new_code is not None:
+ self.utility_code_list.append((new_code, name))
def declare_c_class(self, name, pos, defining = 0, implementing = 0,
module_name = None, base_type = None, objstruct_cname = None,
class StructOrUnionScope(Scope):
# Namespace of a C struct or union.
+
+ module_scope = None
def __init__(self, name="?"):
Scope.__init__(self, name, None, None)
type = PyrexTypes.CPtrType(type)
entry = self.declare(name, cname, type, pos, visibility)
entry.is_variable = 1
+ if self.module_scope:
+ py_name = self.module_scope.get_string_const(name, identifier=True)
+ self.module_scope.add_py_string(py_name)
+ entry.py_name = py_name
self.var_entries.append(entry)
if type.is_pyobject and not allow_pyobject:
error(pos,