diff --git a/efl/eo/efl.eo.pyx b/efl/eo/efl.eo.pyx index 20dc136..8fc41bf 100644 --- a/efl/eo/efl.eo.pyx +++ b/efl/eo/efl.eo.pyx @@ -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 = 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 = 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 = 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): """ diff --git a/efl/eolian/__init__.pyx b/efl/eolian/__init__.pyx index da7d769..a128ddb 100644 --- a/efl/eolian/__init__.pyx +++ b/efl/eolian/__init__.pyx @@ -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: diff --git a/scripts/converters.py b/scripts/converters.py index 6fc786c..a73044a 100644 --- a/scripts/converters.py +++ b/scripts/converters.py @@ -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 <%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 = "tmp" + return ret + else: + return get_alias(tp2) + return get_alias(tp) + else: + log.error("Unhandled event type %s" % (tp.type)) + return diff --git a/scripts/eolian_generate.py b/scripts/eolian_generate.py index 2541419..50a14e8 100755 --- a/scripts/eolian_generate.py +++ b/scripts/eolian_generate.py @@ -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():