Eolian: WIP

This commit is contained in:
Kai Huuhko 2014-10-01 19:13:52 +03:00
parent a795ec8c10
commit 2ba244d263
4 changed files with 213 additions and 46 deletions

View File

@ -34,6 +34,7 @@ from efl.c_eo cimport Eo as cEo, eo_init, eo_shutdown, eo_del, eo_do, \
cimport efl.eo.enums as enums
from efl.utils.logger cimport add_logger
from efl.utils.conversions cimport _ctouni
# Set this to public and export it in pxd if you need it in another module
cdef int PY_EFL_EO_LOG_DOMAIN = add_logger(__name__).eina_log_domain
@ -196,30 +197,76 @@ cdef Eina_Bool _eo_event_del_cb(void *data, cEo *obj,
return enums.EO_CALLBACK_STOP
cdef Eina_Bool _py_efl_eo_event_cb(
void *data, cEo *obj, const Eo_Event_Description *desc, void *event_info):
void *data, cEo *obj,
const Eo_Event_Description *desc,
void *event_info
) with gil:
cdef:
void* tmp
void *tmp1
void *tmp2
bint ret
Eo o
EventDesc py_ev_desc
#EventInfo py_ev_info_obj
func = <object>data
o = object_from_instance(obj)
# create event description python object
py_ev_desc = EventDesc.__new__(EventDesc)
py_ev_desc.desc = desc
tmp = eina_hash_find(o.event_conv_mapping, desc)
if tmp == NULL:
py_ev_info_obj = None
else:
py_ev_info_cls = <object>tmp
#tmp1 = eina_hash_find(o.event_conv_to_py_mapping, desc)
#tmp2 = eina_hash_find(o.event_conv_to_c_mapping, desc)
#if tmp1 == NULL:
# py_ev_info_obj = None
#else:
#py_ev_info_cls = <object>tmp
# use a generic class and set some conv func??
#py_ev_info_obj = py_ev_info_cls.__new__(py_ev_info_cls)
#py_ev_info_obj = EventInfo.__new__(EventInfo)
#py_ev_info_obj.event_info = event_info
#py_ev_info_obj.conv_to_python = tmp1
#py_ev_info_obj.conv_to_c = tmp2
#ret = func(py_ev_desc, py_ev_info_obj) # o as first param?
#return ret
cdef class EventDesc(object):
cdef Eo_Event_Description *desc
def __init__(self):
pass
property name:
def __get__(self):
return _ctouni(self.desc.name)
property doc:
def __get__(self):
return _ctouni(self.desc.doc)
property unfreezable:
def __get__(self):
return bool(self.desc.unfreezable)
#cdef class EventStruct(object):
# cdef:
# void *event_info
# property value:
# def __get__(self):
# return self.conv_to_python(self.event_info)
# def __set__(self, val):
# self.event_info = self.conv_to_c(val)
cdef class Eo(object):
"""

View File

@ -201,51 +201,71 @@ cdef object void_ptr_to_python_obj(void *data, type cls):
cdef Class eolian_class_to_python_obj(const Eolian_Class *o):
if o == NULL:
return None
cdef Class ret = Class.__new__(Class)
ret._set_obj(o)
return ret
cdef Function eolian_func_to_python_obj(const Eolian_Function *o):
if o == NULL:
return None
cdef Function ret = Function.__new__(Function)
ret._set_obj(o)
return ret
cdef FunctionParameter eolian_func_param_to_python_obj(const Eolian_Function_Parameter *o):
if o == NULL:
return None
cdef FunctionParameter ret = FunctionParameter.__new__(FunctionParameter)
ret._set_obj(o)
return ret
cdef Type eolian_type_to_python_obj(const Eolian_Type *o):
if o == NULL:
return None
cdef Type ret = Type.__new__(Type)
ret._set_obj(o)
return ret
cdef TypeStructField eolian_type_struct_field_to_python_obj(const Eolian_Struct_Type_Field *o):
if o == NULL:
return None
cdef TypeStructField ret = TypeStructField.__new__(TypeStructField)
ret._set_obj(o)
return ret
cdef TypeEnumField eolian_type_enum_field_to_python_obj(const Eolian_Enum_Type_Field *o):
if o == NULL:
return None
cdef TypeEnumField ret = TypeEnumField.__new__(TypeEnumField)
ret._set_obj(o)
return ret
cdef Implement eolian_implement_to_python_obj(const Eolian_Implement *o):
if o == NULL:
return None
cdef Implement ret = Implement.__new__(Implement)
ret._set_obj(o)
return ret
cdef Constructor eolian_constructor_to_python_obj(const Eolian_Constructor *o):
if o == NULL:
return None
cdef Constructor ret = Constructor.__new__(Constructor)
ret._set_obj(o)
return ret
cdef Event eolian_event_to_python_obj(const Eolian_Event *o):
if o == NULL:
return None
cdef Event ret = Event.__new__(Event)
ret._set_obj(o)
return ret
cdef Expression eolian_expression_to_python_obj(const Eolian_Expression *o):
if o == NULL:
return None
cdef Expression ret = Expression.__new__(Expression)
ret._set_obj(o)
return ret
@ -256,6 +276,8 @@ cdef Value eolian_value_to_python_obj(Eolian_Value o):
return ret
cdef Variable eolian_variable_to_python_obj(const Eolian_Variable *o):
if o == NULL:
return None
cdef Variable ret = Variable.__new__(Variable)
ret._set_obj(o)
return ret
@ -642,6 +664,8 @@ cdef class Class(object):
cdef const Eolian_Class *klass
cdef _set_obj(self, const Eolian_Class *obj):
if obj == NULL:
raise ValueError("obj is NULL!")
self.klass = obj
def __init__(self):
@ -895,6 +919,8 @@ cdef class Function(object):
cdef const Eolian_Function *function_id
cdef _set_obj(self, const Eolian_Function *obj):
if obj == NULL:
raise ValueError("obj is NULL!")
self.function_id = obj
def __init__(self):
@ -1152,6 +1178,8 @@ cdef class FunctionParameter(object):
cdef const Eolian_Function_Parameter *param
cdef _set_obj(self, const Eolian_Function_Parameter *obj):
if obj == NULL:
raise ValueError("obj is NULL!")
self.param = obj
def __init__(self):
@ -1240,6 +1268,8 @@ cdef class Implement(object):
cdef const Eolian_Implement *impl
cdef _set_obj(self, const Eolian_Implement *obj):
if obj == NULL:
raise ValueError("obj is NULL!")
self.impl = obj
def __init__(self):
@ -1334,6 +1364,8 @@ cdef class Constructor(object):
cdef const Eolian_Constructor *ctor
cdef _set_obj(self, const Eolian_Constructor *obj):
if obj == NULL:
raise ValueError("obj is NULL")
self.ctor = obj
def __init__(self):
@ -1378,6 +1410,8 @@ cdef class Event(object):
cdef const Eolian_Event *event
cdef _set_obj(self, const Eolian_Event *obj):
if obj == NULL:
raise ValueError("obj is NULL!")
self.event = obj
def __init__(self):
@ -1449,6 +1483,8 @@ cdef class Type(object):
cdef const Eolian_Type *tp
cdef _set_obj(self, const Eolian_Type *obj):
if obj == NULL:
raise ValueError("obj is NULL!")
self.tp = obj
def __init__(self):
@ -1468,9 +1504,14 @@ cdef class Type(object):
:return: the alias type or None
"""
cdef Type ret = cls.__new__(cls)
cdef:
Type ret = cls.__new__(cls)
Eolian_Type *obj
if isinstance(name, unicode): name = PyUnicode_AsUTF8String(name)
ret._set_obj(eolian_type_alias_get_by_name(name))
obj = eolian_type_alias_get_by_name(name)
if obj == NULL:
return None
ret._set_obj(obj)
return ret
@classmethod
@ -1481,9 +1522,14 @@ cdef class Type(object):
:return: the struct or None
"""
cdef Type ret = cls.__new__(cls)
cdef:
Type ret = cls.__new__(cls)
Eolian_Type *obj
if isinstance(name, unicode): name = PyUnicode_AsUTF8String(name)
ret._set_obj(eolian_type_struct_get_by_name(name))
obj = eolian_type_struct_get_by_name(name)
if obj == NULL:
return None
ret._set_obj(obj)
return ret
property type:

View File

@ -197,5 +197,32 @@ def conv_type_ret(tp):
return py_ret_type, c_type
def event_conversion_get(tp):
if tp.type != eolian.TypeType.UNKNOWN:
return "Eo_Event_%s" % tp.name
if not tp:
return
if tp.type == eolian.TypeType.UNKNOWN:
return
if tp.type == eolian.TypeType.POINTER:
tp = tp.base_type
if tp.type == eolian.TypeType.STRUCT:
#return "EventInfo%s" % tp.name
return "return <dict><%s>" % tp.c_type
elif tp.type == eolian.TypeType.REGULAR:
def get_alias(tp1):
#print(tp1.name, tp1.type)
alias = eolian.Type.alias_get_by_name(tp1.full_name)
if not alias:
log.error("Unhandled event %s type %s" % (tp.c_type, tp.type))
return
tp2 = alias.base_type
if tp2.type == eolian.TypeType.UNKNOWN:
log.error("UGH")
elif tp2.type == eolian.TypeType.STRUCT:
#print(tp2.name, tp2.c_type)
ret = "<dict>tmp"
return ret
else:
return get_alias(tp2)
return get_alias(tp)
else:
log.error("Unhandled event type %s" % (tp.type))
return

View File

@ -40,6 +40,10 @@ from converters import convert_in_param, convert_out_param, conv_type_ret, \
conv_cls_name, EolianTypeError, event_conversion_get
PY_EFL_TOP_LEVEL_PACKAGE = "efl"
generated_pxis = {}
class EolianSkip(Exception):
pass
@ -209,7 +213,7 @@ class Function(object):
for p in func.parameters:
self.c_params.append((p.type.c_type, p.name))
self.c_ret_type = ret_type.c_type if ret_type.type != eolian.TypeType.UNKNOWN else "void"
self.c_ret_type = ret_type.c_type if ret_type else "void"
def cdef_generate(self, gen):
func = self.func
@ -323,7 +327,7 @@ class Function(object):
gen.out_cdefs_write(out_cdefs)
if ret_type.type != eolian.TypeType.UNKNOWN:
if ret_type:
ret_type2 = ret_type.c_type
else:
ret_type2 = None
@ -336,12 +340,12 @@ class Function(object):
py_ret_type, c_ret_type = conv_type_ret(t)
rparams.append((c_ret_type, n))
gen.write("return %s" % (", ".join([r[1] for r in rparams])))
elif ret_type.type != eolian.TypeType.UNKNOWN:
elif ret_type:
ret = self.RET_PARAM
try:
ret_type = convert_out_param(ret_type, ret)
except EolianTypeError:
gen.write("# FIXME: Unknown return type")
gen.write("# FIXME: Unknown return type %s" % ret_type.c_type)
gen.dedent()
raise
gen.write("return %s" % (ret))
@ -486,6 +490,7 @@ class Class(object):
class_counter[cls.name] += 1
self.c_name = cls.name
self.full_c_name = cls.full_name
self.lib_name, self.name = conv_cls_name(cls)
header_path = cls.filename
@ -592,17 +597,27 @@ class Class(object):
gen.write("cdef class _%s(%s):" % (self.name, inherits))
gen.indent()
gen.write("def __cinit__(self):")
gen.indent()
for o in self.events:
try:
o.generate(gen)
except EolianTypeError:
log.info("Skipping %r because of unknown type", o)
except Exception:
log.exception("Error while generating %r", o)
gen.dedent()
gen.write()
if self.events:
gen.write("def __cinit__(self):")
gen.indent()
for o in self.events[:]:
try:
o.generate_name_mapping(gen)
o.generate_conversion_mapping(gen)
except EolianTypeError:
log.info("Skipping %r because of unknown type", o)
except Exception:
log.exception("Error while generating %r", o)
gen.dedent()
gen.write()
for o in self.events[:]:
try:
o.generate_conversion_function(gen)
except EolianTypeError:
log.info("Skipping %r because of unknown type", o)
except Exception:
log.exception("Error while generating %r", o)
if not self.ctor and not self.props and not self.methods:
gen.write("pass")
@ -634,7 +649,7 @@ class Class(object):
gen.dedent()
gen.write()
def py_generate(self, gen):
#def py_generate(self, gen):
inherits = ["_" + self.name]
imports = [(self.lib_name, "_" + self.name)]
for i in self.inherits:
@ -654,7 +669,7 @@ class Class(object):
imports.append((lib_name, "_" + name))
for l, n in imports:
l = l.lower()
l = PY_EFL_TOP_LEVEL_PACKAGE + "." + l.lower()
gen.write("from %s import %s" % (l, n))
gen.write()
@ -674,7 +689,7 @@ class Class(object):
gen.dedent()
gen.dedent()
gen.write()
gen.write('_object_mapping_register("%s", %s)' % (self.c_name, self.name))
gen.write('_object_mapping_register("%s", %s)' % (self.full_c_name.replace(".", "_"), self.name))
gen.write()
@ -701,8 +716,10 @@ class File(object):
if base.type == eolian.TypeType.REGULAR:
gen.write("ctypedef %s %s" % (i.name, base.name))
elif base.type == eolian.TypeType.FUNCTION:
ret = base.return_type.c_type
if ret is None:
ret_type = base.return_type
if ret_type:
ret = ret_type.c_type
else:
ret = "void"
gen.write("ctypedef %s (*%s)(%s)" % (
ret,
@ -752,12 +769,14 @@ class File(object):
self.pyxgen.printout(filepath=pxi_path)
def py_generate(self):
py_path = os.path.join(args.output, "__init__" + ".py")
generated_pxis.setdefault(namespace, []).append(pxi_path)
self.gencls.py_generate(self.pygen)
# def py_generate(self):
# py_path = os.path.join(args.output, "__init__" + ".py")
self.pygen.printout(filepath=py_path, append=True)
# self.gencls.py_generate(self.pygen)
# self.pygen.printout(filepath=py_path, append=True)
class Event(object):
@ -767,19 +786,37 @@ class Event(object):
def cdef_generate(self, gen):
gen.write("enum: %s" % (self.event.c_name))
def generate(self, gen):
def generate_name_mapping(self, gen):
gen.write(
'eina_hash_set(self.event_desc_mapping, "%s", %s)' % (
self.event.name, self.event.c_name
)
)
def generate_conversion_mapping(self, gen):
conv = event_conversion_get(self.event.type)
if conv:
gen.write(
'eina_hash_set(self.event_conv_mapping, %s, %s)' % (
self.event.c_name, conv
'eina_hash_set(self.event_conv_mapping, %s, self._event_conv_%s_to_python)' % (
self.event.c_name, self.event.name.replace(",", "_")
)
)
else:
pass #print("{0} - {1}".format(self.event.name, self.event.type.c_type))
def generate_conversion_function(self, gen):
conv = event_conversion_get(self.event.type)
if conv:
gen.write(
'cdef object _event_conv_%s_to_python(self, void *evi):' % (
self.event.name.replace(",", "_")
)
)
gen.indent()
gen.write('cdef {0} tmp = <{0}>evi'.format(self.event.type.c_type))
gen.write('return ' + conv)
gen.dedent()
gen.write()
class_counter = Counter()
@ -821,11 +858,21 @@ for path in args.paths:
log.exception("Exception while generating pyx for %s" % (filename))
continue
try:
eolf.py_generate()
except Exception:
log.exception("Exception while generating py for %s" % (filename))
continue
# try:
# eolf.py_generate()
# except Exception:
# log.exception("Exception while generating py for %s" % (filename))
# continue
for ns, pxis in generated_pxis.items():
filename = os.path.join(args.output, "generated_" + ns + ".pxi")
if os.path.exists(filename):
log.error("File %s exists, removing" % (filename))
with open(filename, "a") as f:
for pxi in pxis:
line = 'include "%s"\n' % (pxi)
f.write(line)
def report():