diff options
author | Felipe Magno de Almeida <felipe@expertisesolutions.com.br> | 2019-01-17 21:33:09 +0900 |
---|---|---|
committer | Felipe Magno de Almeida <felipe@expertisesolutions.com.br> | 2019-01-17 21:36:27 +0900 |
commit | adc2e674af528c01ca5bb11d56edc475bce5cc4d (patch) | |
tree | 670312a6280387fbba6c25eeea23ea10beb22dfe | |
parent | 7b342e8fddaff50dd62354f357a3d249afc77498 (diff) | |
download | efl-adc2e674af528c01ca5bb11d56edc475bce5cc4d.tar.gz |
eolian-mono: Add interface registration to inherited classes
Summary: Depends on D7635, D7634
Reviewers: woohyun, bu5hm4n, segfaultxavi, lauromoura
Reviewed By: woohyun
Subscribers: cedric, #reviewers, #committers
Tags: #efl
Differential Revision: https://phab.enlightenment.org/D7636
-rw-r--r-- | src/bin/eolian_mono/eolian/mono/function_definition.hh | 10 | ||||
-rw-r--r-- | src/bin/eolian_mono/eolian/mono/function_registration.hh | 30 | ||||
-rw-r--r-- | src/bin/eolian_mono/eolian/mono/klass.hh | 178 | ||||
-rw-r--r-- | src/bin/eolian_mono/eolian/mono/name_helpers.hh | 12 | ||||
-rw-r--r-- | src/bindings/mono/eo_mono/iwrapper.cs | 104 | ||||
-rw-r--r-- | src/tests/efl_mono/Inheritance.cs | 4 |
6 files changed, 196 insertions, 142 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/function_definition.hh b/src/bin/eolian_mono/eolian/mono/function_definition.hh index 763bbc451f..2d9e1b5d5a 100644 --- a/src/bin/eolian_mono/eolian/mono/function_definition.hh +++ b/src/bin/eolian_mono/eolian/mono/function_definition.hh @@ -71,7 +71,11 @@ struct native_function_definition_generator if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context)) return false; - std::string klass_inherit_name = name_helpers::klass_inherit_name(*klass); + std::string klass_cast_name; + if (klass->type != attributes::class_type::interface_) + klass_cast_name = name_helpers::klass_inherit_name(*klass); + else + klass_cast_name = name_helpers::klass_interface_name(*klass); if(!as_generator (scope_tab @@ -89,7 +93,7 @@ struct native_function_definition_generator << scope_tab << scope_tab << "if(wrapper != null) {\n" << scope_tab << scope_tab << scope_tab << eolian_mono::native_function_definition_preamble() << scope_tab << scope_tab << scope_tab << "try {\n" - << scope_tab << scope_tab << scope_tab << scope_tab << (return_type != " void" ? "_ret_var = " : "") << "((" << klass_inherit_name << ")wrapper)." << string + << scope_tab << scope_tab << scope_tab << scope_tab << (return_type != " void" ? "_ret_var = " : "") << "((" << klass_cast_name << ")wrapper)." << string << "(" << (native_argument_invocation % ", ") << ");\n" << scope_tab << scope_tab << scope_tab << "} catch (Exception e) {\n" << scope_tab << scope_tab << scope_tab << scope_tab << "Eina.Log.Warning($\"Callback error: {e.ToString()}\");\n" @@ -98,7 +102,7 @@ struct native_function_definition_generator << eolian_mono::native_function_definition_epilogue(*klass) << scope_tab << scope_tab << "} else {\n" << scope_tab << scope_tab << scope_tab << (return_type != " void" ? "return " : "") << string - << "(Efl.Eo.Globals.efl_super(obj, " << "EoKlass)" << *(", " << argument) << ");\n" + << "(Efl.Eo.Globals.efl_super(obj, " << "GetEflClass())" << *(", " << argument) << ");\n" << scope_tab << scope_tab << "}\n" << scope_tab << "}\n" ) diff --git a/src/bin/eolian_mono/eolian/mono/function_registration.hh b/src/bin/eolian_mono/eolian/mono/function_registration.hh index 0b8da4a05a..78f2d718c7 100644 --- a/src/bin/eolian_mono/eolian/mono/function_registration.hh +++ b/src/bin/eolian_mono/eolian/mono/function_registration.hh @@ -20,10 +20,10 @@ namespace eolian_mono { -template <typename I> +// template <typename I> struct function_registration_generator { - I index_generator; + // I index_generator; attributes::klass_def const* klass; template <typename OutputIterator, typename Context> @@ -34,7 +34,7 @@ struct function_registration_generator return true; else { - auto index = index_generator(); + // auto index = index_generator(); if(!as_generator( scope_tab << scope_tab << f.c_name << "_static_delegate = new " << f.c_name << "_delegate(" << @@ -43,12 +43,13 @@ struct function_registration_generator return false; if(!as_generator + (scope_tab << scope_tab << "descs.Add(new Efl_Op_Description() {" #ifdef _WIN32 - (scope_tab << scope_tab << "descs[" << index << "].api_func = Marshal.StringToHGlobalAnsi(\"" << string << "\");\n" + << "api_func = Marshal.StringToHGlobalAnsi(\"" << string << "\")" #else - (scope_tab << scope_tab << "descs[" << index << "].api_func = Efl.Eo.Globals.dlsym(Efl.Eo.Globals.RTLD_DEFAULT, \"" << string << "\");\n" + << "api_func = Efl.Eo.Globals.dlsym(Efl.Eo.Globals.RTLD_DEFAULT, \"" << string << "\")" #endif - << scope_tab << scope_tab << "descs[" << index << "].func = Marshal.GetFunctionPointerForDelegate(" << string << "_static_delegate);\n" + ", func = Marshal.GetFunctionPointerForDelegate(" << string << "_static_delegate)});\n" ) .generate(sink, std::make_tuple(f.c_name, f.c_name), context)) return false; @@ -59,10 +60,9 @@ struct function_registration_generator struct function_registration_parameterized { - template <typename I> - function_registration_generator<I> operator()(I i, attributes::klass_def const& klass) const + function_registration_generator operator()(attributes::klass_def const& klass) const { - return {i, &klass}; + return {&klass}; } } const function_registration; @@ -70,15 +70,15 @@ struct function_registration_parameterized namespace efl { namespace eolian { namespace grammar { -template <typename I> -struct is_eager_generator< ::eolian_mono::function_registration_generator<I>> : std::true_type {}; -template <typename I> -struct is_generator< ::eolian_mono::function_registration_generator<I>> : std::true_type {}; +template <> +struct is_eager_generator< ::eolian_mono::function_registration_generator> : std::true_type {}; +template <> +struct is_generator< ::eolian_mono::function_registration_generator> : std::true_type {}; namespace type_traits { -template <typename I> -struct attributes_needed< ::eolian_mono::function_registration_generator<I>> : std::integral_constant<int, 1> {}; +template <> +struct attributes_needed< ::eolian_mono::function_registration_generator> : std::integral_constant<int, 1> {}; } } } } diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh index 5dc22f5d38..c3d430e24c 100644 --- a/src/bin/eolian_mono/eolian/mono/klass.hh +++ b/src/bin/eolian_mono/eolian/mono/klass.hh @@ -123,58 +123,57 @@ struct klass // Interface class if(class_type == "interface") { - auto iface_cxt = context_add_tag(class_context{class_context::interface}, context); + auto iface_cxt = context_add_tag(class_context{class_context::interface}, context); - if(!as_generator(documentation).generate(sink, cls, iface_cxt)) - return false; + if(!as_generator(documentation).generate(sink, cls, iface_cxt)) + return false; - // Mark the interface with the proper native Efl_Class* getter - if(!as_generator(lit("[") << name_helpers::interface_native_getter_attr_name(cls) << "]\n") - .generate(sink, attributes::unused, iface_cxt)) - return false; + // Mark the interface with the proper native Efl_Class* getter + if(!as_generator(lit("[") << name_helpers::klass_native_inherit_name(cls) << "]\n") + .generate(sink, attributes::unused, iface_cxt)) + return false; - if(!as_generator + if(!as_generator ( "public " /*<< class_type*/ "interface" /*<<*/ " " << string << " : " ) .generate(sink, name_helpers::klass_interface_name(cls), iface_cxt)) - return false; - for(auto first = std::begin(cls.immediate_inherits) - , last = std::end(cls.immediate_inherits); first != last; ++first) - { - if(first->type != attributes::class_type::regular && first->type != attributes::class_type::abstract_) - if(!as_generator("\n" << scope_tab << string << " ,").generate(sink, name_helpers::klass_full_interface_name(*first), iface_cxt)) - return false; - } + return false; + for(auto first = std::begin(cls.immediate_inherits) + , last = std::end(cls.immediate_inherits); first != last; ++first) + { + if(first->type != attributes::class_type::regular && first->type != attributes::class_type::abstract_) + if(!as_generator("\n" << scope_tab << string << " ,").generate(sink, name_helpers::klass_full_interface_name(*first), iface_cxt)) + return false; + } - if(!as_generator("\n" << scope_tab << "Efl.Eo.IWrapper, IDisposable").generate(sink, attributes::unused, iface_cxt)) - return false; + if(!as_generator("\n" << scope_tab << "Efl.Eo.IWrapper, IDisposable").generate(sink, attributes::unused, iface_cxt)) + return false; - if(!as_generator("\n{\n").generate(sink, attributes::unused, iface_cxt)) - return false; + if(!as_generator("\n{\n").generate(sink, attributes::unused, iface_cxt)) + return false; - if(!as_generator(*(scope_tab << function_declaration)).generate(sink, cls.functions, iface_cxt)) - return false; + if(!as_generator(*(scope_tab << function_declaration)).generate(sink, cls.functions, iface_cxt)) + return false; - if(!as_generator(*(scope_tab << async_function_declaration)).generate(sink, cls.functions, iface_cxt)) - return false; + if(!as_generator(*(scope_tab << async_function_declaration)).generate(sink, cls.functions, iface_cxt)) + return false; - if(!as_generator(*(event_declaration)).generate(sink, cls.events, iface_cxt)) - return false; + if(!as_generator(*(event_declaration)).generate(sink, cls.events, iface_cxt)) + return false; - for (auto &&p : cls.parts) - if (!as_generator( + for (auto &&p : cls.parts) + if (!as_generator( documentation(1) << name_helpers::klass_full_concrete_or_interface_name(p.klass) << " " << utils::capitalize(p.name) << "{ get;}\n" ).generate(sink, p, iface_cxt)) - return false; - - if (!as_generator(*(property_wrapper_definition)).generate(sink, cls.properties, iface_cxt)) - return false; + return false; - // End of interface declaration - if(!as_generator("}\n").generate(sink, attributes::unused, iface_cxt)) return false; + if (!as_generator(*(property_wrapper_definition)).generate(sink, cls.properties, iface_cxt)) + return false; + // End of interface declaration + if(!as_generator("}\n").generate(sink, attributes::unused, iface_cxt)) return false; } // Events arguments go in the top namespace to avoid the Concrete suffix clutter in interface events. @@ -276,17 +275,6 @@ struct klass if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false; - - // Attribute getter of the native 'Efl_Class *' handle (for proper inheritance from additional explicit interfaces) - if(!as_generator(lit("public class ") << name_helpers::interface_native_getter_attr_name(cls) << " : Efl.Eo.NativeGetterAttr\n" - << "{\n" - << scope_tab << "public override IntPtr GetEflClass()\n" - << scope_tab << "{\n" - << scope_tab << scope_tab << "return " << name_helpers::klass_get_full_name(cls) << "();\n" - << scope_tab << "}\n" - << "}\n") - .generate(sink, attributes::unused, concrete_cxt)) - return false; } // Inheritable class @@ -298,6 +286,7 @@ struct klass if(!as_generator ( documentation + << "[" << name_helpers::klass_native_inherit_name(cls) << "]\n" << "public " << class_type << " " << name_helpers::klass_concrete_name(cls) << " : " << (klass_full_concrete_or_interface_name % ",") // classes << (inherit_classes.empty() ? "" : ",") @@ -359,16 +348,8 @@ struct klass if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false; } - std::size_t function_count = get_implementable_function_count(cls); - - int function_registration_index = 0; - auto index_generator = [&function_registration_index] - { - return function_registration_index++; - }; - // Native Inherit class - if(class_type == "class") + //if(class_type == "class") { auto inative_cxt = context_add_tag(class_context{class_context::inherit_native}, context); auto native_inherit_name = name_helpers::klass_native_inherit_name(cls); @@ -382,21 +363,21 @@ struct klass if(!as_generator ( - "public " << class_type << " " << native_inherit_name << " " << (root ? "" : (": " + base_name)) <<"{\n" - << scope_tab << (root ? "protected IntPtr EoKlass { get; set; }\n" : "\n") - << scope_tab << "public " << (root ? "" : "new ") << "Efl_Op_Description[] GetEoOps()\n" + "public class " << native_inherit_name << " " << (root ? ": Efl.Eo.NativeClass" : (": " + base_name)) <<"{\n" + // << scope_tab << (root ? "protected IntPtr EoKlass { get; set; }\n" : "\n") + << scope_tab << "public " << /*(root ? "" : "new ")*/ "override " << "System.Collections.Generic.List<Efl_Op_Description> GetEoOps(System.Type type)\n" << scope_tab << "{\n" - << scope_tab << scope_tab << "Efl_Op_Description[] descs = new Efl_Op_Description[" << grammar::int_ << "];\n" + << scope_tab << scope_tab << "var descs = new System.Collections.Generic.List<Efl_Op_Description>();\n" ) - .generate(sink, function_count, inative_cxt)) + .generate(sink, attributes::unused, inative_cxt)) return false; // Native wrapper registration - if(!as_generator(*(function_registration(index_generator, cls))) + if(!as_generator(*(function_registration(cls))) .generate(sink, helpers::get_all_implementable_methods(cls), inative_cxt)) return false; if(!root) - if(!as_generator(scope_tab << scope_tab << "descs = descs.Concat(base.GetEoOps()).ToArray();\n").generate(sink, attributes::unused, inative_cxt)) + if(!as_generator(scope_tab << scope_tab << "descs.AddRange(base.GetEoOps(type));\n").generate(sink, attributes::unused, inative_cxt)) return false; if(!as_generator( @@ -405,32 +386,23 @@ struct klass ).generate(sink, attributes::unused, inative_cxt)) return false; - if(!as_generator - (scope_tab << "public " << (root ? "" : "new " ) << "byte class_initializer(IntPtr klass)\n" - << scope_tab << "{\n" - << scope_tab << scope_tab << "var descs = GetEoOps();\n" - << scope_tab << scope_tab << "var count = descs.Length;\n" - << scope_tab << scope_tab << "IntPtr descs_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(descs[0])*count);\n" - << scope_tab << scope_tab << "IntPtr ptr = descs_ptr;\n" - << scope_tab << scope_tab << "for(int i = 0; i != count; ++i)\n" - << scope_tab << scope_tab << "{\n" - << scope_tab << scope_tab << scope_tab << "Marshal.StructureToPtr(descs[i], ptr, false);\n" - << scope_tab << scope_tab << scope_tab << "ptr = IntPtr.Add(ptr, Marshal.SizeOf(descs[0]));\n" - << scope_tab << scope_tab << "}\n" - << scope_tab << scope_tab << "Efl_Object_Ops ops;\n" - << scope_tab << scope_tab << "ops.descs = descs_ptr;\n" - << scope_tab << scope_tab << "ops.count = (UIntPtr)count;\n" - << scope_tab << scope_tab << "IntPtr ops_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ops));\n" - << scope_tab << scope_tab << "Marshal.StructureToPtr(ops, ops_ptr, false);\n" - << scope_tab << scope_tab << "Efl.Eo.Globals.efl_class_functions_set(klass, ops_ptr, IntPtr.Zero);\n" - << scope_tab << scope_tab << "EoKlass = klass;\n" - ).generate(sink, attributes::unused, inative_cxt)) return false; - - - if(!as_generator(scope_tab << scope_tab << "return 1;\n" - << scope_tab << "}\n") - .generate(sink, attributes::unused, inative_cxt)) return false; - // + // Attribute getter of the native 'Efl_Class *' handle (for proper inheritance from additional explicit interfaces) + if(!as_generator( + scope_tab << "public override IntPtr GetEflClass()\n" + << scope_tab << "{\n" + << scope_tab << scope_tab << "return " << name_helpers::klass_get_full_name(cls) << "();\n" + << scope_tab << "}\n" + ).generate(sink, attributes::unused, inative_cxt)) + return false; + + if(!as_generator( + scope_tab << "public static " << (root ? "" : "new ") << " IntPtr GetEflClassStatic()\n" + << scope_tab << "{\n" + << scope_tab << scope_tab << "return " << name_helpers::klass_get_full_name(cls) << "();\n" + << scope_tab << "}\n" + ).generate(sink, attributes::unused, inative_cxt)) + return false; + // Native method definitions if(!as_generator(*(native_function_definition(cls))) .generate(sink, helpers::get_all_implementable_methods(cls), inative_cxt)) return false; @@ -451,8 +423,9 @@ struct klass bool root = !helpers::has_regular_ancestor(cls); bool is_inherit = is_inherit_context(context); - std::string class_getter = "return Efl.Eo.Globals.efl_class_get(handle);"; + std::string class_getter = name_helpers::klass_get_name(cls) + "()"; std::string native_inherit_full_name = name_helpers::klass_full_native_inherit_name(cls); + auto inherit_name = name_helpers::klass_concrete_name(cls); // The klass field is static but there is no problem if multiple C# classes inherit from this generated one // as it is just a simple wrapper, forwarding the Eo calls either to the user API (where C#'s virtual method @@ -464,7 +437,6 @@ struct klass << scope_tab << "public " << (root ? "" : "new ") << "static " << native_inherit_full_name << " nativeInherit = new " << native_inherit_full_name << "();\n" ).generate(sink, attributes::unused, context)) return false; - class_getter = "return klass;"; } std::string raw_klass_modifier; @@ -477,7 +449,10 @@ struct klass scope_tab << "///<summary>Pointer to the native class description.</summary>\n" << scope_tab << "public " << raw_klass_modifier << "System.IntPtr NativeClass {\n" << scope_tab << scope_tab << "get {\n" - << scope_tab << scope_tab << scope_tab << class_getter << "\n" //return klass; }\n" + << scope_tab << scope_tab << scope_tab << "if (((object)this).GetType() == typeof (" << inherit_name << "))\n" + << scope_tab << scope_tab << scope_tab << scope_tab << "return " << native_inherit_full_name << ".GetEflClassStatic();\n" + << scope_tab << scope_tab << scope_tab << "else\n" + << scope_tab << scope_tab << scope_tab << scope_tab << "return Efl.Eo.Globals.klasses[((object)this).GetType()];\n" << scope_tab << scope_tab << "}\n" << scope_tab << "}\n" ).generate(sink, attributes::unused, context)) @@ -534,7 +509,8 @@ struct klass scope_tab << "///<summary>Creates a new instance.</summary>\n" << scope_tab << "///<param name=\"parent\">Parent instance.</param>\n" << scope_tab << "///<param name=\"init_cb\">Delegate to call constructing methods that should be run inside the constructor.</param>\n" - << scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : base(nativeInherit.class_initializer, \"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent, ref klass)\n" + << scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : " + "base(\"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent)\n" << scope_tab << "{\n" << scope_tab << scope_tab << "if (init_cb != null) {\n" << scope_tab << scope_tab << scope_tab << "init_cb(this);\n" @@ -543,7 +519,7 @@ struct klass << scope_tab << "}\n" << scope_tab << "///<summary>Internal constructor to forward the wrapper initialization to the root class.</summary>\n" - << scope_tab << "protected " << inherit_name << "(Efl.Eo.Globals.class_initializer class_initializer, String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent, ref IntPtr target_klass) : base(class_initializer, klass_name, base_klass, managed_type, parent, ref target_klass) {}\n" + << scope_tab << "protected " << inherit_name << "(String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent) : base(klass_name, base_klass, managed_type, parent) {}\n" << scope_tab << "///<summary>Constructs an instance from a native pointer.</summary>\n" << scope_tab << "public " << inherit_name << "(System.IntPtr raw)" << (root ? "" : " : base(raw)") << "\n" @@ -559,7 +535,7 @@ struct klass scope_tab << "///<summary>Creates a new instance.</summary>\n" << scope_tab << "///<param name=\"parent\">Parent instance.</param>\n" << scope_tab << "///<param name=\"init_cb\">Delegate to call constructing methods that should be run inside the constructor.</param>\n" - << scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : this(nativeInherit.class_initializer, \"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent, ref klass)\n" + << scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : this(\"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent)\n" << scope_tab << "{\n" << scope_tab << scope_tab << "if (init_cb != null) {\n" << scope_tab << scope_tab << scope_tab << "init_cb(this);\n" @@ -567,22 +543,22 @@ struct klass << scope_tab << scope_tab << "FinishInstantiation();\n" << scope_tab << "}\n" - << scope_tab << "protected " << inherit_name << "(Efl.Eo.Globals.class_initializer class_initializer, String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent, ref IntPtr target_klass)\n" + << scope_tab << "protected " << inherit_name << "(String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent)\n" << scope_tab << "{\n" - << scope_tab << scope_tab << "inherited = this.GetType() != managed_type;\n" + << scope_tab << scope_tab << "inherited = ((object)this).GetType() != managed_type;\n" << scope_tab << scope_tab << "IntPtr actual_klass = base_klass;\n" << scope_tab << scope_tab << "if (inherited) {\n" - << scope_tab << scope_tab << scope_tab << "if (target_klass == System.IntPtr.Zero) {\n" + << scope_tab << scope_tab << scope_tab << "if (!Efl.Eo.Globals.klasses.ContainsKey(((object)this).GetType())) {\n" << scope_tab << scope_tab << scope_tab << scope_tab << "lock (klassAllocLock) {\n" - << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "if (target_klass == System.IntPtr.Zero) {\n" - << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "target_klass = Efl.Eo.Globals.register_class(class_initializer, klass_name, base_klass, this.GetType());\n" - << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "if (target_klass == System.IntPtr.Zero) {\n" + << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "actual_klass = Efl.Eo.Globals.register_class(klass_name, base_klass, ((object)this).GetType());\n" + << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "if (actual_klass == System.IntPtr.Zero) {\n" << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "throw new System.InvalidOperationException(\"Failed to initialize class '" << inherit_name << "'\");\n" << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "}\n" - << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "}\n" + << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "Efl.Eo.Globals.klasses[((object)this).GetType()] = actual_klass;\n" << scope_tab << scope_tab << scope_tab << scope_tab << "}\n" << scope_tab << scope_tab << scope_tab << "}\n" - << scope_tab << scope_tab << scope_tab << "actual_klass = target_klass;\n" + << scope_tab << scope_tab << scope_tab << "else\n" + << scope_tab << scope_tab << scope_tab << scope_tab << "actual_klass = Efl.Eo.Globals.klasses[((object)this).GetType()];\n" << scope_tab << scope_tab << "}\n" << scope_tab << scope_tab << "handle = Efl.Eo.Globals.instantiate_start(actual_klass, parent);\n" << scope_tab << scope_tab << "register_event_proxies();\n" diff --git a/src/bin/eolian_mono/eolian/mono/name_helpers.hh b/src/bin/eolian_mono/eolian/mono/name_helpers.hh index a5cf5c0149..8910447ae1 100644 --- a/src/bin/eolian_mono/eolian/mono/name_helpers.hh +++ b/src/bin/eolian_mono/eolian/mono/name_helpers.hh @@ -379,18 +379,6 @@ inline std::string klass_get_full_name(T const& clsname) return klass_full_concrete_name(clsname) + "." + klass_get_name(clsname); } -template<typename T> -inline std::string interface_native_getter_attr_name(T const& clsname) -{ - return klass_interface_name(clsname) + "NativeGetterAttr"; -} - -template<typename T> -inline std::string interface_native_getter_attr_full_name(T const& clsname) -{ - return klass_full_interface_name(clsname) + "NativeGetterAttr"; -} - // Events inline std::string managed_event_name(std::string const& name) { diff --git a/src/bindings/mono/eo_mono/iwrapper.cs b/src/bindings/mono/eo_mono/iwrapper.cs index fee5a23e34..fe96088626 100644 --- a/src/bindings/mono/eo_mono/iwrapper.cs +++ b/src/bindings/mono/eo_mono/iwrapper.cs @@ -150,11 +150,14 @@ public class Globals { [DllImport(efl.Libs.Eo)] public static extern IntPtr efl_object_legacy_only_event_description_get([MarshalAs(UnmanagedType.LPStr)] String name); + public static System.Collections.Concurrent.ConcurrentDictionary<System.Type, System.IntPtr> klasses + = new System.Collections.Concurrent.ConcurrentDictionary<System.Type, System.IntPtr>(); + public const int RTLD_NOW = 2; public delegate byte class_initializer(IntPtr klass); - - public static IntPtr register_class(class_initializer initializer, String class_name, IntPtr base_klass, System.Type type) + + public static IntPtr register_class(String class_name, IntPtr base_klass, System.Type type) { ClassDescription description; description.version = 2; // EO_VERSION @@ -165,39 +168,113 @@ public class Globals { description.class_constructor = IntPtr.Zero; description.class_destructor = IntPtr.Zero; - if(initializer != null) - description.class_initializer = Marshal.GetFunctionPointerForDelegate(initializer); + class_initializer init = (IntPtr kls) => + { + return Globals.class_initializer_call(kls, type); + }; + + description.class_initializer = Marshal.GetFunctionPointerForDelegate(init); IntPtr description_ptr = Eina.MemoryNative.Alloc(Marshal.SizeOf(description)); Marshal.StructureToPtr(description, description_ptr, false); var interface_list = EoG.get_efl_interfaces(type); + System.Console.WriteLine ("Interafaces: {0}", interface_list.Count); + Eina.Log.Debug("Going to register!"); IntPtr klass = EoG.call_efl_class_new(description_ptr, base_klass, interface_list); if(klass == IntPtr.Zero) + { Eina.Log.Error("klass was not registered"); + Console.WriteLine("klass was not registered"); + } else Eina.Log.Debug("Registered class successfully"); return klass; } public static List<IntPtr> get_efl_interfaces(System.Type type) { + System.Type base_type = type.BaseType; + var ifaces_lst = new List<IntPtr>(); + var base_ifaces = base_type.GetInterfaces(); var ifaces = type.GetInterfaces(); foreach (var iface in ifaces) { - var attrs = System.Attribute.GetCustomAttributes(iface); - foreach (var attr in attrs) + if (!System.Array.Exists(base_ifaces, element => element == iface)) { - if (attr is Efl.Eo.NativeGetterAttr) { - ifaces_lst.Add(((Efl.Eo.NativeGetterAttr)attr).GetEflClass()); + var attrs = System.Attribute.GetCustomAttributes(iface); + foreach (var attr in attrs) + { + if (attr is Efl.Eo.NativeClass) { + ifaces_lst.Add(((Efl.Eo.NativeClass)attr).GetEflClass()); break; - } + } + } } } return ifaces_lst; } + private static Efl.Eo.NativeClass get_native_class(System.Type type) + { + var attrs = System.Attribute.GetCustomAttributes(type); + foreach (var attr in attrs) + { + if (attr is Efl.Eo.NativeClass) { + return (Efl.Eo.NativeClass)attr; + } + } + return null; + } + public static byte class_initializer_call(IntPtr klass, System.Type type) + { + Console.WriteLine("class_intiailizer_call 0x{1} {0}", type, klass); + Efl.Eo.NativeClass nativeClass = get_native_class(type.BaseType); + + if (nativeClass != null) + { + Console.WriteLine("nativeClass != null"); + var descs = nativeClass.GetEoOps(type); + var count = descs.Count; + + var all_interfaces = type.GetInterfaces(); + var base_interfaces = type.BaseType.GetInterfaces(); + foreach (var iface in all_interfaces) + { + if (!System.Array.Exists(base_interfaces, element => element == iface)) + { + var nc = get_native_class(iface); + if(nc != null) + { + var moredescs = nc.GetEoOps(type); + Console.WriteLine("adding {0} more descs to registration", moredescs.Count); + descs.AddRange(moredescs); + count = descs.Count; + } + } + } + + IntPtr descs_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(descs[0])*count); + IntPtr ptr = descs_ptr; + for(int i = 0; i != count; ++i) + { + Marshal.StructureToPtr(descs[i], ptr, false); + ptr = IntPtr.Add(ptr, Marshal.SizeOf(descs[0])); + } + Efl_Object_Ops ops; + ops.descs = descs_ptr; + ops.count = (UIntPtr)count; + IntPtr ops_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ops)); + Marshal.StructureToPtr(ops, ops_ptr, false); + Efl.Eo.Globals.efl_class_functions_set(klass, ops_ptr, IntPtr.Zero); + //EoKlass = klass; + } + else + Console.WriteLine("nativeClass == null"); + + return 1; + } public static IntPtr call_efl_class_new(IntPtr desc, IntPtr bk, List<IntPtr> il = null) { IntPtr nul = IntPtr.Zero; @@ -259,11 +336,17 @@ public class Globals { public static IntPtr instantiate_start(IntPtr klass, Efl.Object parent) { Eina.Log.Debug($"Instantiating from klass 0x{klass.ToInt64():x}"); + Console.WriteLine($"Instantiating from klass 0x{klass.ToInt64():x}"); System.IntPtr parent_ptr = System.IntPtr.Zero; if(parent != null) parent_ptr = parent.NativeHandle; System.IntPtr eo = Efl.Eo.Globals._efl_add_internal_start("file", 0, klass, parent_ptr, 1, 0); + if (eo == System.IntPtr.Zero) + { + throw new Exception("Instantiation failed"); + } + Console.WriteLine($"Eo instance right after internal_start 0x{eo.ToInt64():x} with refcount {Efl.Eo.Globals.efl_ref_count(eo)}"); Console.WriteLine($"Parent was 0x{parent_ptr.ToInt64()}"); return eo; @@ -415,9 +498,10 @@ public static class Config AllowMultiple = false, Inherited = true) ] -public abstract class NativeGetterAttr : System.Attribute +public abstract class NativeClass : System.Attribute { public abstract IntPtr GetEflClass(); + public abstract System.Collections.Generic.List<Efl_Op_Description> GetEoOps(System.Type type); } public interface IWrapper diff --git a/src/tests/efl_mono/Inheritance.cs b/src/tests/efl_mono/Inheritance.cs index 30ca391e87..344c6da71f 100644 --- a/src/tests/efl_mono/Inheritance.cs +++ b/src/tests/efl_mono/Inheritance.cs @@ -24,11 +24,13 @@ class TestInheritance { override public void IntOut (int x, out int y) { + Console.WriteLine("IntOut"); y = 10*x; } public string StringshareTest (string i) { + Console.WriteLine("StringshareTest"); return "Hello World"; } } @@ -44,8 +46,8 @@ class TestInheritance { var obj = new Inherit2(); int i = Dummy.InheritHelper.ReceiveDummyAndCallIntOut(obj); - string s = Dummy.InheritHelper.ReceiveDummyAndCallInStringshare(obj); Test.AssertEquals (50, i); + string s = Dummy.InheritHelper.ReceiveDummyAndCallInStringshare(obj); Test.AssertEquals ("Hello World", s); } } |