diff --git a/src/bin/eolian_mono/eolian/mono/function_definition.hh b/src/bin/eolian_mono/eolian/mono/function_definition.hh
index 2821360a04..756136007c 100644
--- a/src/bin/eolian_mono/eolian/mono/function_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_definition.hh
@@ -75,7 +75,7 @@ struct native_function_definition_generator
if(!as_generator
(scope_tab
- << " private static "
+ << " private "
<< eolian_mono::marshall_type(true) << " "
<< string
<< "(System.IntPtr obj, System.IntPtr pd"
@@ -98,7 +98,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, " << klass_inherit_name << ".klass)" << *(", " << argument) << ");\n"
+ << "(Efl.Eo.Globals.efl_super(obj, " << "EoKlass)" << *(", " << argument) << ");\n"
<< scope_tab << scope_tab << "}\n"
<< scope_tab << "}\n"
)
@@ -114,13 +114,10 @@ struct native_function_definition_generator
, context))
return false;
- if(!as_generator
- (scope_tab << "private static "
- << string
- << "_delegate "
- << string << "_static_delegate = new " << string << "_delegate(" << name_helpers::klass_native_inherit_name(*klass) << "." << string << ");\n"
- )
- .generate(sink, std::make_tuple(f.c_name, f.c_name, f.c_name, escape_keyword(f.name)), context))
+ // This is the delegate that will be passed to Eo to be called from C.
+ if(!as_generator(
+ scope_tab << "private " << f.c_name << "_delegate " << f.c_name << "_static_delegate;\n"
+ ).generate(sink, attributes::unused, context))
return false;
return true;
}
diff --git a/src/bin/eolian_mono/eolian/mono/function_helpers.hh b/src/bin/eolian_mono/eolian/mono/function_helpers.hh
index 06bf5d44ec..017ddad9d8 100644
--- a/src/bin/eolian_mono/eolian/mono/function_helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_helpers.hh
@@ -41,7 +41,7 @@ struct native_function_definition_preamble_generator
).generate(sink, std::make_tuple(f.parameters, f.parameters, f.parameters, f.return_type), context))
return false;
- return true;
+ return as_generator("\n").generate(sink, attributes::unused, context);
}
};
diff --git a/src/bin/eolian_mono/eolian/mono/function_registration.hh b/src/bin/eolian_mono/eolian/mono/function_registration.hh
index e8a41047f9..0b8da4a05a 100644
--- a/src/bin/eolian_mono/eolian/mono/function_registration.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_registration.hh
@@ -35,14 +35,20 @@ struct function_registration_generator
else
{
auto index = index_generator();
-
+
+ if(!as_generator(
+ scope_tab << scope_tab << f.c_name << "_static_delegate = new " << f.c_name << "_delegate(" <<
+ escape_keyword(f.name) << ");\n"
+ ).generate(sink, attributes::unused, context))
+ return false;
+
if(!as_generator
#ifdef _WIN32
(scope_tab << scope_tab << "descs[" << index << "].api_func = Marshal.StringToHGlobalAnsi(\"" << string << "\");\n"
#else
(scope_tab << scope_tab << "descs[" << index << "].api_func = Efl.Eo.Globals.dlsym(Efl.Eo.Globals.RTLD_DEFAULT, \"" << string << "\");\n"
#endif
- << scope_tab << scope_tab << "descs[" << index << "].func = Marshal.GetFunctionPointerForDelegate(" << name_helpers::klass_native_inherit_name(*klass) << "." << string << "_static_delegate);\n"
+ << scope_tab << scope_tab << "descs[" << index << "].func = Marshal.GetFunctionPointerForDelegate(" << string << "_static_delegate);\n"
)
.generate(sink, std::make_tuple(f.c_name, f.c_name), context))
return false;
diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh
index f10c3a38d4..90133291a8 100644
--- a/src/bin/eolian_mono/eolian/mono/klass.hh
+++ b/src/bin/eolian_mono/eolian/mono/klass.hh
@@ -357,10 +357,19 @@ struct klass
{
auto inative_cxt = context_add_tag(class_context{class_context::inherit_native}, context);
auto native_inherit_name = name_helpers::klass_native_inherit_name(cls);
+ auto inherit_name = name_helpers::klass_inherit_name(cls);
+ std::string base_name;
+ if(!root)
+ {
+ attributes::klass_def parent_klass(get_klass(*cls.parent, cls.unit), cls.unit);
+ base_name = name_helpers::klass_full_native_inherit_name(parent_klass);
+ }
+
if(!as_generator
(
- "internal " << class_type << " " << native_inherit_name << " {\n"
- << scope_tab << "public static byte class_initializer(IntPtr klass)\n"
+ "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"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "Efl_Op_Description[] descs = new Efl_Op_Description[" << grammar::int_ << "];\n"
)
@@ -371,20 +380,35 @@ struct klass
if(!as_generator(*(function_registration(index_generator, 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))
+ return false;
+
+ if(!as_generator(
+ scope_tab << scope_tab << "return descs;\n"
+ << scope_tab << "}\n"
+ ).generate(sink, attributes::unused, inative_cxt))
+ return false;
+
if(!as_generator
- ( scope_tab << scope_tab << "IntPtr descs_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(descs[0])*" << function_count << ");\n"
+ (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 != " << function_count << "; ++i)\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)" << function_count << ";\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;
@@ -413,6 +437,7 @@ struct klass
bool is_inherit = is_inherit_context(context);
std::string class_getter = "return Efl.Eo.Globals.efl_class_get(handle);";
+ std::string native_inherit_full_name = name_helpers::klass_full_native_inherit_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
@@ -421,6 +446,7 @@ struct klass
{
if(!as_generator(
scope_tab << "public " << (root ? "" : "new ") << "static System.IntPtr klass = System.IntPtr.Zero;\n"
+ << 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;";
@@ -493,7 +519,7 @@ struct klass
scope_tab << "///Creates a new instance.\n"
<< scope_tab << "///Parent instance.\n"
<< scope_tab << "///Delegate to call constructing methods that should be run inside the constructor.\n"
- << scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : base(" << native_inherit_name << ".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(nativeInherit.class_initializer, \"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent, ref klass)\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "if (init_cb != null) {\n"
<< scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
@@ -518,7 +544,7 @@ struct klass
scope_tab << "///Creates a new instance.\n"
<< scope_tab << "///Parent instance.\n"
<< scope_tab << "///Delegate to call constructing methods that should be run inside the constructor.\n"
- << scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : this(" << native_inherit_name << ".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(nativeInherit.class_initializer, \"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent, ref klass)\n"
<< scope_tab << "{\n"
<< scope_tab << scope_tab << "if (init_cb != null) {\n"
<< scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
diff --git a/src/bin/eolian_mono/eolian/mono/name_helpers.hh b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
index 06291f412c..cfda7229f6 100644
--- a/src/bin/eolian_mono/eolian/mono/name_helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
@@ -353,6 +353,12 @@ inline std::string klass_native_inherit_name(T const& klass)
return klass_concrete_name(klass) + "NativeInherit";
}
+template
+inline std::string klass_full_native_inherit_name(T const& klass)
+{
+ return klass_full_concrete_name(klass) + "NativeInherit";
+}
+
template
inline std::string klass_get_name(T const& clsname)
{
diff --git a/src/bin/eolian_mono/eolian_mono.cc b/src/bin/eolian_mono/eolian_mono.cc
index 328b983052..2e0e8918cb 100644
--- a/src/bin/eolian_mono/eolian_mono.cc
+++ b/src/bin/eolian_mono/eolian_mono.cc
@@ -131,6 +131,7 @@ run(options_type const& opts)
if (!as_generator("using System;\n"
"using System.Runtime.InteropServices;\n"
"using System.Collections.Generic;\n"
+ "using System.Linq;\n"
"using System.ComponentModel;\n")
.generate(iterator, efl::eolian::grammar::attributes::unused, efl::eolian::grammar::context_null()))
{
diff --git a/src/bindings/mono/eo_mono/iwrapper.cs b/src/bindings/mono/eo_mono/iwrapper.cs
index 11e9fa8091..35ee606540 100644
--- a/src/bindings/mono/eo_mono/iwrapper.cs
+++ b/src/bindings/mono/eo_mono/iwrapper.cs
@@ -141,6 +141,10 @@ public class Globals {
public static IntPtr cached_string_to_intptr(Dictionary dict, String str)
{
IntPtr ptr = IntPtr.Zero;
+
+ if (str == null)
+ return ptr;
+
if (!dict.TryGetValue(str, out ptr))
{
ptr = Eina.StringConversion.ManagedStringToNativeUtf8Alloc(str);
@@ -153,6 +157,10 @@ public class Globals {
public static IntPtr cached_stringshare_to_intptr(Dictionary dict, String str)
{
IntPtr ptr = IntPtr.Zero;
+
+ if (str == null)
+ return ptr;
+
if (!dict.TryGetValue(str, out ptr))
{
ptr = Eina.Stringshare.eina_stringshare_add(str);
diff --git a/src/tests/efl_mono/Eo.cs b/src/tests/efl_mono/Eo.cs
index 7d5df72457..5567f1ef33 100644
--- a/src/tests/efl_mono/Eo.cs
+++ b/src/tests/efl_mono/Eo.cs
@@ -345,4 +345,39 @@ class TestCsharpProperties
}
}
+class TestEoGrandChildrenFinalize
+{
+ public sealed class Child : Dummy.TestObject
+ {
+ public int receivedValue = 0;
+ public override Efl.Object FinalizeAdd()
+ {
+ receivedValue = 42;
+ return this;
+ }
+ }
+
+ public static void test_grand_children_finalize()
+ {
+ Child obj = new Child();
+ Test.AssertEquals(42, obj.receivedValue);
+ }
+
+ public sealed class GrandChild : Dummy.Child
+ {
+ public int receivedValue = 0;
+ public override Efl.Object FinalizeAdd()
+ {
+ receivedValue = -42;
+ return this;
+ }
+ }
+
+ public static void test_grand_grand_children_finalize()
+ {
+ GrandChild obj = new GrandChild();
+ Test.AssertEquals(-42, obj.receivedValue);
+ }
+}
+
}
diff --git a/src/tests/efl_mono/libefl_mono_native_test.c b/src/tests/efl_mono/libefl_mono_native_test.c
index 52876e6859..841c6a92c6 100644
--- a/src/tests/efl_mono/libefl_mono_native_test.c
+++ b/src/tests/efl_mono/libefl_mono_native_test.c
@@ -36,6 +36,7 @@
#include "dummy_numberwrapper.eo.h"
#include "dummy_test_object.eo.h"
+#include "dummy_child.eo.h"
#include "dummy_test_iface.eo.h"
#include "dummy_another_iface.eo.h"
@@ -66,6 +67,10 @@ typedef struct Dummy_Numberwrapper_Data
int number;
} Dummy_Numberwrapper_Data;
+typedef struct Dummy_Child_Data
+{
+} Dummy_Child_Data;
+
static
void *_new_int(int v)
@@ -3898,8 +3903,29 @@ int _dummy_test_object_dummy_test_iface_iface_prop_get(EINA_UNUSED const Eo *obj
return pd->iface_prop;
}
+/// Dummy.Child
+static Efl_Object *
+_dummy_child_efl_object_constructor(Eo *obj, EINA_UNUSED Dummy_Child_Data *pd)
+{
+ efl_constructor(efl_super(obj, DUMMY_CHILD_CLASS));
+ return obj;
+}
+
+EOLIAN static void
+_dummy_child_class_constructor(Efl_Class *klass)
+{
+ (void)klass;
+}
+
+EOLIAN static void
+_dummy_child_class_destructor(Efl_Class *klass)
+{
+ (void)klass;
+}
+
#include "dummy_test_object.eo.c"
#include "dummy_numberwrapper.eo.c"
+#include "dummy_child.eo.c"
#include "dummy_test_iface.eo.c"
#include "dummy_another_iface.eo.c"