Commit ef83d2ab authored by Robert Bradshaw's avatar Robert Bradshaw

struct to object via dict

parent 820e1291
...@@ -3351,7 +3351,8 @@ class TypecastNode(ExprNode): ...@@ -3351,7 +3351,8 @@ class TypecastNode(ExprNode):
if from_py and not to_py and self.operand.is_ephemeral() and not self.type.is_numeric: 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") error(self.pos, "Casting temporary Python object to non-numeric non-Python type")
if to_py and not from_py: 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.result_ctype = py_object_type
self.operand = self.operand.coerce_to_pyobject(env) self.operand = self.operand.coerce_to_pyobject(env)
else: else:
...@@ -4388,10 +4389,10 @@ class CoerceToPyTypeNode(CoercionNode): ...@@ -4388,10 +4389,10 @@ class CoerceToPyTypeNode(CoercionNode):
self.type = py_object_type self.type = py_object_type
self.gil_check(env) self.gil_check(env)
self.is_temp = 1 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, error(arg.pos,
"Cannot convert '%s' to Python object" % arg.type) "Cannot convert '%s' to Python object" % arg.type)
gil_message = "Converting to Python object" gil_message = "Converting to Python object"
def analyse_types(self, env): def analyse_types(self, env):
......
...@@ -42,6 +42,7 @@ vtable_prefix = pyrex_prefix + "vtable_" ...@@ -42,6 +42,7 @@ vtable_prefix = pyrex_prefix + "vtable_"
vtabptr_prefix = pyrex_prefix + "vtabptr_" vtabptr_prefix = pyrex_prefix + "vtabptr_"
vtabstruct_prefix = pyrex_prefix + "vtabstruct_" vtabstruct_prefix = pyrex_prefix + "vtabstruct_"
opt_arg_prefix = pyrex_prefix + "opt_args_" opt_arg_prefix = pyrex_prefix + "opt_args_"
convert_func_prefix = pyrex_prefix + "convert_"
args_cname = pyrex_prefix + "args" args_cname = pyrex_prefix + "args"
pykwdlist_cname = pyrex_prefix + "pyargnames" pykwdlist_cname = pyrex_prefix + "pyargnames"
......
...@@ -404,7 +404,10 @@ class CType(PyrexType): ...@@ -404,7 +404,10 @@ class CType(PyrexType):
from_py_function = None from_py_function = None
exception_value = None exception_value = None
exception_check = 1 exception_check = 1
def create_convert_utility_code(self, env):
return True
def error_condition(self, result_code): def error_condition(self, result_code):
conds = [] conds = []
if self.is_string: if self.is_string:
...@@ -932,6 +935,41 @@ class CStructOrUnionType(CType): ...@@ -932,6 +935,41 @@ class CStructOrUnionType(CType):
self.scope = scope self.scope = scope
self.typedef_flag = typedef_flag self.typedef_flag = typedef_flag
self.is_struct = kind == 'struct' 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): def __repr__(self):
return "<CStructOrUnionType %s %s%s>" % (self.name, self.cname, return "<CStructOrUnionType %s %s%s>" % (self.name, self.cname,
...@@ -1076,6 +1114,9 @@ class ErrorType(PyrexType): ...@@ -1076,6 +1114,9 @@ class ErrorType(PyrexType):
from_py_function = "dummy" from_py_function = "dummy"
typestring = None typestring = None
def create_convert_utility_code(self, env):
return True
def declaration_code(self, entity_code, def declaration_code(self, entity_code,
for_display = 0, dll_linkage = None, pyrex = 0): for_display = 0, dll_linkage = None, pyrex = 0):
return "<error>" return "<error>"
......
...@@ -359,6 +359,8 @@ class Scope: ...@@ -359,6 +359,8 @@ class Scope:
self.type_entries.append(entry) self.type_entries.append(entry)
if not scope and not entry.type.scope: if not scope and not entry.type.scope:
self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos) self.check_for_illegal_incomplete_ctypedef(typedef_flag, pos)
if scope and self.outer_scope:
scope.module_scope = self
return entry return entry
def check_previous_typedef_flag(self, entry, typedef_flag, pos): def check_previous_typedef_flag(self, entry, typedef_flag, pos):
...@@ -959,7 +961,8 @@ class ModuleScope(Scope): ...@@ -959,7 +961,8 @@ class ModuleScope(Scope):
return "%s%s%d" % (Naming.const_prefix, prefix, n) return "%s%s%d" % (Naming.const_prefix, prefix, n)
def use_utility_code(self, new_code, name=None): 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, def declare_c_class(self, name, pos, defining = 0, implementing = 0,
module_name = None, base_type = None, objstruct_cname = None, module_name = None, base_type = None, objstruct_cname = None,
...@@ -1203,6 +1206,8 @@ class GeneratorLocalScope(LocalScope): ...@@ -1203,6 +1206,8 @@ class GeneratorLocalScope(LocalScope):
class StructOrUnionScope(Scope): class StructOrUnionScope(Scope):
# Namespace of a C struct or union. # Namespace of a C struct or union.
module_scope = None
def __init__(self, name="?"): def __init__(self, name="?"):
Scope.__init__(self, name, None, None) Scope.__init__(self, name, None, None)
...@@ -1216,6 +1221,10 @@ class StructOrUnionScope(Scope): ...@@ -1216,6 +1221,10 @@ class StructOrUnionScope(Scope):
type = PyrexTypes.CPtrType(type) type = PyrexTypes.CPtrType(type)
entry = self.declare(name, cname, type, pos, visibility) entry = self.declare(name, cname, type, pos, visibility)
entry.is_variable = 1 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) self.var_entries.append(entry)
if type.is_pyobject and not allow_pyobject: if type.is_pyobject and not allow_pyobject:
error(pos, error(pos,
......
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