summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitor Sousa <vitorsousa@expertisesolutions.com.br>2019-06-04 18:43:07 -0300
committerVitor Sousa <vitorsousa@expertisesolutions.com.br>2019-06-04 18:52:47 -0300
commit55d557e444f30135dc304e4e8e5eba7c959ea84f (patch)
tree3e634f35467545380f96e5fcca20d410a5a1292f
parentc2865a90ef75320f5ceb00abb03076b8363aa867 (diff)
downloadefl-devs/vitorsousa/constructible_eflsharp.tar.gz
csharp: make inherited C# classes constructible from native Cdevs/vitorsousa/constructible_eflsharp
With this commit it is now possible for a class that inherits from a C# binding class to be instantiated from native C code. It only has to provide a constructor that receives an `Efl.Eo.EoWrapper.ConstructingHandle` struct, and which calls the base binding constructor passing it. For example: `private Type(ConstructingHandle ch) : base(ch) {}`. Add some test files to validate the proper behavior of this feature. Add some small fixes in generation contexts in order to properly generate base constructors.
-rw-r--r--src/Makefile_Efl_Mono.am9
-rw-r--r--src/bin/eolian_mono/eolian/mono/klass.hh24
-rw-r--r--src/bindings/mono/eo_mono/EoWrapper.cs105
-rw-r--r--src/bindings/mono/eo_mono/iwrapper.cs11
-rw-r--r--src/lib/efl_mono/efl_custom_exports_mono.c10
-rw-r--r--src/tests/efl_mono/EoConstruction.cs79
-rw-r--r--src/tests/efl_mono/dummy_constructible_object.c70
-rw-r--r--src/tests/efl_mono/dummy_constructible_object.eo47
-rw-r--r--src/tests/efl_mono/dummy_test_object.c6
-rw-r--r--src/tests/efl_mono/libefl_mono_native_test.h1
-rw-r--r--src/tests/efl_mono/meson.build3
11 files changed, 352 insertions, 13 deletions
diff --git a/src/Makefile_Efl_Mono.am b/src/Makefile_Efl_Mono.am
index 0cf41589ff..3d04368ccf 100644
--- a/src/Makefile_Efl_Mono.am
+++ b/src/Makefile_Efl_Mono.am
@@ -70,6 +70,7 @@ efl_mono_test_eolian_files = \
tests/efl_mono/dummy_inherit_iface.eo \
tests/efl_mono/dummy_inherit_helper.eo \
tests/efl_mono/dummy_child.eo \
+ tests/efl_mono/dummy_constructible_object.eo \
tests/efl_mono/dummy_part_holder.eo \
tests/efl_mono/dummy_numberwrapper.eo \
tests/efl_mono/dummy_event_manager.eo
@@ -403,6 +404,7 @@ tests_efl_mono_libefl_mono_native_test_la_SOURCES = \
tests/efl_mono/dummy_interfaces.c \
tests/efl_mono/dummy_numberwrapper.c \
tests/efl_mono/dummy_part_holder.c \
+ tests/efl_mono/dummy_constructible_object.c \
tests/efl_mono/dummy_test_object.c
efl_mono_test_eolian_c = $(efl_mono_test_eolian_files:%.eo=%.eo.c)
@@ -447,6 +449,11 @@ tests/efl_mono/dummy_part_holder.c: \
$(efl_mono_test_eolian_h) \
tests/efl_mono/libefl_mono_native_test.h
+tests/efl_mono/dummy_constructible_object.c: \
+ $(efl_mono_test_eolian_c) \
+ $(efl_mono_test_eolian_h) \
+ tests/efl_mono/libefl_mono_native_test.h
+
tests/efl_mono/dummy_test_object.c: \
$(efl_mono_test_eolian_c) \
$(efl_mono_test_eolian_h) \
@@ -455,6 +462,7 @@ tests/efl_mono/dummy_test_object.c: \
# Intermediate C Sharp test DLL
efl_mono_test_eolian_mono_files = tests/efl_mono/dummy_test_object.eo.cs \
tests/efl_mono/dummy_test_iface.eo.cs \
+tests/efl_mono/dummy_constructible_object.eo.cs \
tests/efl_mono/dummy_child.eo.cs \
tests/efl_mono/dummy_event_manager.eo.cs \
tests/efl_mono/dummy_part_holder.eo.cs \
@@ -509,6 +517,7 @@ tests_efl_mono_efl_mono_SOURCES = \
tests/efl_mono/Eldbus.cs \
tests/efl_mono/Eo.cs \
tests/efl_mono/EoPromises.cs \
+ tests/efl_mono/EoConstruction.cs \
tests/efl_mono/Errors.cs \
tests/efl_mono/Events.cs \
tests/efl_mono/FunctionPointers.cs \
diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh
index 6ac4aa1c3c..8b018f6413 100644
--- a/src/bin/eolian_mono/eolian/mono/klass.hh
+++ b/src/bin/eolian_mono/eolian/mono/klass.hh
@@ -198,6 +198,17 @@ struct klass
if (!as_generator
(
+ scope_tab << "/// <summary>Constructor to be used when objects are expected to be constructed from native code.</summary>\n"
+ << scope_tab << "/// <param name=\"ch\">Tag struct storing the native handle of the object being constructed.</param>\n"
+ << scope_tab << "private " << concrete_name << "(ConstructingHandle ch) : base(ch)\n"
+ << scope_tab << "{\n"
+ << scope_tab << "}\n\n"
+ )
+ .generate(sink, attributes::unused, concrete_cxt))
+ return false;
+
+ if (!as_generator
+ (
scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(concrete_cxt).actual_library_name(cls.filename)
<< ")] internal static extern System.IntPtr\n"
<< scope_tab << scope_tab << name_helpers::klass_get_name(cls) << "();\n"
@@ -246,7 +257,7 @@ struct klass
).generate(sink, attributes::unused, concrete_cxt))
return false;
- if(!generate_native_inherit_class(sink, cls, change_indentation(indent.inc(), context)))
+ if(!generate_native_inherit_class(sink, cls, change_indentation(indent.inc(), concrete_cxt)))
return true;
if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false;
@@ -318,7 +329,7 @@ struct klass
).generate(sink, attributes::unused, inherit_cxt))
return false;
- if(!generate_native_inherit_class(sink, cls, change_indentation(indent.inc(), context)))
+ if(!generate_native_inherit_class(sink, cls, change_indentation(indent.inc(), inherit_cxt)))
return true;
if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false;
@@ -357,7 +368,7 @@ struct klass
(
indent << lit("/// <summary>Wrapper for native methods and virtual method delegates.\n")
<< indent << "/// For internal use by generated code only.</summary>\n"
- << indent << "public " << (root ? "" : "new " ) << "class " << native_inherit_name << " " << (root ? " : Efl.Eo.NativeClass" : (": " + base_name)) <<"\n"
+ << indent << "public new class " << native_inherit_name << " : " << (root ? "Efl.Eo.EoWrapper.NativeMethods" : base_name) << "\n"
<< indent << "{\n"
).generate(sink, attributes::unused, inative_cxt))
return false;
@@ -396,7 +407,7 @@ struct klass
).generate(sink, attributes::unused, inative_cxt))
return false;
- if(!root)
+ if (!root || context_find_tag<class_context>(context).current_wrapper_kind != class_context::concrete)
if(!as_generator(indent << scope_tab << scope_tab << "descs.AddRange(base.GetEoOps(type));\n").generate(sink, attributes::unused, inative_cxt))
return false;
@@ -492,6 +503,11 @@ struct klass
<< (*(scope_tab << scope_tab << constructor_invocation << "\n"))
<< scope_tab << scope_tab << "FinishInstantiation();\n"
<< scope_tab << "}\n\n"
+ << scope_tab << "/// <summary>Constructor to be used when objects are expected to be constructed from native code.</summary>\n"
+ << scope_tab << "/// <param name=\"ch\">Tag struct storing the native handle of the object being constructed.</param>\n"
+ << scope_tab << "protected " << inherit_name << "(ConstructingHandle ch) : base(ch)\n"
+ << scope_tab << "{\n"
+ << scope_tab << "}\n\n"
<< scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.\n"
<< scope_tab << "/// Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.</summary>\n"
<< scope_tab << "/// <param name=\"raw\">The native pointer to be wrapped.</param>\n"
diff --git a/src/bindings/mono/eo_mono/EoWrapper.cs b/src/bindings/mono/eo_mono/EoWrapper.cs
index e1174a9fe8..0899b8682c 100644
--- a/src/bindings/mono/eo_mono/EoWrapper.cs
+++ b/src/bindings/mono/eo_mono/EoWrapper.cs
@@ -2,6 +2,7 @@ using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Threading;
+using System.Reflection;
namespace Efl
{
@@ -62,6 +63,32 @@ public abstract class EoWrapper : IWrapper, IDisposable
private static Efl.EventCb ownershipUniqueDelegate = new Efl.EventCb(OwnershipUniqueCallback);
private static Efl.EventCb ownershipSharedDelegate = new Efl.EventCb(OwnershipSharedCallback);
+
+ /// <summary>Constructor to be used when objects are expected to be constructed from native code.
+ /// For a class that inherited from an EFL# class to be properly constructed from native code
+ /// one must create a constructor with this signature and calls this base constructor from it.
+ /// This constructor will take care of calling base constructors of the native classes and
+ /// perform additional setup so objects are ready to use.
+ /// It is advisable to check for the <see cref="NativeHandle"/> property in the top level
+ /// constructor and signal an error when it has a value of IntPtr.Zero after this
+ /// constructor completion.
+ /// Warning: Do not use this constructor directly from a `new` statement.</summary>
+ /// <param name="ch">Tag struct storing the native handle of the object being constructed.</param>
+ protected EoWrapper(ConstructingHandle ch)
+ {
+ handle = Efl.Eo.Globals.efl_constructor(Efl.Eo.Globals.efl_super(ch.NativeHandle, Efl.Eo.Globals.efl_class_get(ch.NativeHandle)));
+ if (handle == IntPtr.Zero)
+ {
+ Eina.Log.Warning("Natice constructor returned NULL");
+ return;
+ }
+
+ AddWrapperSupervisor();
+ // Make an additional reference to C#
+ // - Will also call EVENT_OWNERSHIP_SHARED
+ Efl.Eo.Globals.efl_ref(handle);
+ }
+
/// <summary>Initializes a new instance of the <see cref="Object"/> class.
/// Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.</summary>
/// <param name="raw">The native pointer to be wrapped.</param>
@@ -98,7 +125,17 @@ public abstract class EoWrapper : IWrapper, IDisposable
parent_ptr = parent.NativeHandle;
}
- handle = Efl.Eo.Globals._efl_add_internal_start(file, line, actual_klass, parent_ptr, 1, 0);
+ if (!inherited)
+ {
+ handle = Efl.Eo.Globals._efl_add_internal_start(file, line, actual_klass, parent_ptr, 1, 0);
+ }
+ else
+ {
+ handle = Efl.Eo.Globals._efl_add_internal_start_bindings(file, line, actual_klass, parent_ptr, 1, 0,
+ Efl.Eo.Globals.efl_mono_avoid_top_level_constructor_callback_addr_get(),
+ IntPtr.Zero);
+ }
+
if (handle == System.IntPtr.Zero)
{
throw new Exception("Instantiation failed");
@@ -297,8 +334,72 @@ public abstract class EoWrapper : IWrapper, IDisposable
AddNativeEventHandler("eo", "_EFL_EVENT_OWNERSHIP_SHARED", ownershipSharedDelegate, ownershipSharedDelegate);
Eina.Error.RaiseIfUnhandledException();
}
+
+ protected struct ConstructingHandle
+ {
+ public ConstructingHandle(IntPtr h)
+ {
+ NativeHandle = h;
+ }
+
+ public IntPtr NativeHandle { get; set; }
+ }
+
+ public abstract class NativeMethods : Efl.Eo.NativeClass
+ {
+ private static EflConstructorSelegate csharpEflConstructorStaticDelegate = new EflConstructorSelegate(Constructor);
+ private static Efl.Eo.NativeModule EoModule = new Efl.Eo.NativeModule("eo");
+
+ private delegate IntPtr EflConstructorSelegate(IntPtr obj, IntPtr pd);
+
+ public override System.Collections.Generic.List<Efl_Op_Description> GetEoOps(Type type)
+ {
+ var descs = new System.Collections.Generic.List<Efl_Op_Description>();
+
+ descs.Add(new Efl_Op_Description()
+ {
+ api_func = Efl.Eo.FunctionInterop.LoadFunctionPointer(EoModule.Module, "efl_constructor"),
+ func = Marshal.GetFunctionPointerForDelegate(csharpEflConstructorStaticDelegate)
+ });
+
+ return descs;
+ }
+
+ private static IntPtr Constructor(IntPtr obj, IntPtr pd)
+ {
+ try
+ {
+ var eoKlass = Efl.Eo.Globals.efl_class_get(obj);
+ var managedType = ClassRegister.GetManagedType(eoKlass);
+ if (managedType == null)
+ {
+ IntPtr nativeName = Efl.Eo.Globals.efl_class_name_get(eoKlass);
+ var name = Eina.StringConversion.NativeUtf8ToManagedString(nativeName);
+ Eina.Log.Warning($"Can't get Managed class for object handle 0x{(UInt64)obj:x} with native class [{name}]");
+ return IntPtr.Zero;
+ }
+
+ var flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
+ ConstructorInfo constructor = managedType.GetConstructor(flags, null, new Type[1] { typeof(ConstructingHandle) }, null);
+ var eoWrapper = (Efl.Eo.IWrapper) constructor.Invoke(new object[1] { new ConstructingHandle(obj) });
+ if (eoWrapper == null)
+ {
+ Eina.Log.Warning("Constructor was unable to create a new object");
+ return IntPtr.Zero;
+ }
+
+ return eoWrapper.NativeHandle;
+ }
+ catch (Exception e)
+ {
+ Eina.Log.Warning($"Inherited constructor error: {e.ToString()}");
+ Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION);
+ return IntPtr.Zero;
+ }
+ }
+ }
}
-} // namespace Global
+} // namespace Eo
} // namespace Efl
diff --git a/src/bindings/mono/eo_mono/iwrapper.cs b/src/bindings/mono/eo_mono/iwrapper.cs
index 9e73ca4687..618d16ca0f 100644
--- a/src/bindings/mono/eo_mono/iwrapper.cs
+++ b/src/bindings/mono/eo_mono/iwrapper.cs
@@ -44,10 +44,6 @@ public class Globals
public static FunctionWrapper<efl_object_shutdown_delegate> efl_object_shutdown_ptr = new FunctionWrapper<efl_object_shutdown_delegate>(efl.Libs.EoModule, "efl_object_shutdown");
public static void efl_object_shutdown() => efl_object_shutdown_ptr.Value.Delegate();
// [DllImport(efl.Libs.Eo)] public static extern void efl_object_shutdown();
- public static FunctionWrapper<_efl_add_internal_start_delegate> _efl_add_internal_start_ptr = new FunctionWrapper<_efl_add_internal_start_delegate>(efl.Libs.EoModule, "_efl_add_internal_start");
- public delegate IntPtr
- _efl_add_internal_start_delegate([MarshalAs(UnmanagedType.LPStr)] String file, int line,
- IntPtr klass, IntPtr parent, byte is_ref, byte is_fallback);
[DllImport(efl.Libs.CustomExports)] public static extern IntPtr efl_mono_wrapper_supervisor_get(IntPtr eo);
[DllImport(efl.Libs.CustomExports)] public static extern void efl_mono_wrapper_supervisor_set(IntPtr eo, IntPtr ws);
@@ -55,6 +51,9 @@ public class Globals
[DllImport(efl.Libs.Eo)] public static extern IntPtr
_efl_add_internal_start([MarshalAs(UnmanagedType.LPStr)] String file, int line,
IntPtr klass, IntPtr parent, byte is_ref, byte is_fallback);
+ [DllImport(efl.Libs.Eo)] public static extern IntPtr
+ _efl_add_internal_start_bindings([MarshalAs(UnmanagedType.LPStr)] String file, int line, IntPtr klass, IntPtr parent,
+ byte is_ref, byte is_fallback, IntPtr substitute_ctor, IntPtr data);
public delegate IntPtr
_efl_add_end_delegate(IntPtr eo, byte is_ref, byte is_fallback);
[DllImport(efl.Libs.Eo)] public static extern IntPtr
@@ -196,6 +195,10 @@ public class Globals
public delegate IntPtr dlerror_delegate();
[DllImport(efl.Libs.Evil)] public static extern IntPtr dlerror();
+ [DllImport(efl.Libs.Eo)] public static extern IntPtr efl_constructor(IntPtr obj);
+
+ [DllImport(efl.Libs.CustomExports)] public static extern IntPtr efl_mono_avoid_top_level_constructor_callback_addr_get();
+
[DllImport(efl.Libs.Eo)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
efl_event_callback_priority_add(IntPtr obj, IntPtr desc, short priority, IntPtr cb, IntPtr data);
diff --git a/src/lib/efl_mono/efl_custom_exports_mono.c b/src/lib/efl_mono/efl_custom_exports_mono.c
index 55f0054da0..a11a11e4b6 100644
--- a/src/lib/efl_mono/efl_custom_exports_mono.c
+++ b/src/lib/efl_mono/efl_custom_exports_mono.c
@@ -166,6 +166,16 @@ EAPI Eina_Free_Cb efl_mono_native_efl_unref_addr_get()
return (Eina_Free_Cb)efl_mono_thread_safe_efl_unref;
}
+static Eo *_efl_mono_avoid_top_level_constructor_cb(void *data EINA_UNUSED, Eo *obj)
+{
+ return efl_constructor(efl_super(obj, efl_class_get(obj)));
+}
+
+EAPI Efl_Substitute_Ctor_Cb efl_mono_avoid_top_level_constructor_callback_addr_get()
+{
+ return &_efl_mono_avoid_top_level_constructor_cb;
+}
+
// Iterator Wrapper //
typedef struct _Eina_Iterator_Wrapper_Mono
diff --git a/src/tests/efl_mono/EoConstruction.cs b/src/tests/efl_mono/EoConstruction.cs
new file mode 100644
index 0000000000..cd4a774bd1
--- /dev/null
+++ b/src/tests/efl_mono/EoConstruction.cs
@@ -0,0 +1,79 @@
+using System;
+
+class InheritedConstructibleObject : Dummy.ConstructibleObject
+{
+ public InheritedConstructibleObject()
+ {
+ if (this.NativeConstructionCount != 1)
+ {
+ DefaultConstrutorCallCount = -100;
+ }
+
+ ++DefaultConstrutorCallCount;
+ this.IncrementDefaultConstructionCount();
+ }
+
+ private InheritedConstructibleObject(ConstructingHandle ch) : base(ch)
+ {
+ if (this.NativeConstructionCount != 1)
+ {
+ SpecialConstrutorCallCount = -100;
+ }
+
+ ++SpecialConstrutorCallCount;
+ this.IncrementSpecialConstructionCount();
+ }
+
+ public int DefaultConstrutorCallCount { get; set; } = 0;
+ public int SpecialConstrutorCallCount { get; set; } = 0;
+}
+
+namespace TestSuite
+{
+
+class TestEoConstruction
+{
+ public static void TestGeneratedEoDirectConstruction()
+ {
+ var obj = new Dummy.ConstructibleObject();
+ Test.AssertEquals(obj.NativeConstructionCount, 1);
+ Test.AssertEquals(obj.DefaultConstructionCount, 0);
+ Test.AssertEquals(obj.SpecialConstructionCount, 0);
+ obj.Dispose();
+ }
+
+ public static void TestInheritedEoDirectConstruction()
+ {
+ var obj = new InheritedConstructibleObject();
+ Test.AssertEquals(obj.NativeConstructionCount, 1);
+ Test.AssertEquals(obj.DefaultConstructionCount, 1);
+ Test.AssertEquals(obj.SpecialConstructionCount, 0);
+ Test.AssertEquals(obj.DefaultConstrutorCallCount, 1);
+ Test.AssertEquals(obj.SpecialConstrutorCallCount, 0);
+ obj.Dispose();
+ }
+
+ public static void TestInheritedEoIndirectConstruction()
+ {
+ var obj = new Dummy.ConstructibleObject();
+ Test.AssertEquals(obj.NativeConstructionCount, 1);
+ Test.AssertEquals(obj.DefaultConstructionCount, 0);
+ Test.AssertEquals(obj.SpecialConstructionCount, 0);
+
+ var obj2 = (InheritedConstructibleObject) obj.ConstructTypeAndStore(typeof(InheritedConstructibleObject));
+ Test.AssertEquals(obj2.NativeConstructionCount, 1);
+ Test.AssertEquals(obj2.DefaultConstructionCount, 0);
+ Test.AssertEquals(obj2.SpecialConstructionCount, 1);
+ Test.AssertEquals(obj2.DefaultConstrutorCallCount, 0);
+ Test.AssertEquals(obj2.SpecialConstrutorCallCount, 1);
+
+ var internalObj = obj.InternalObject;
+ Test.Assert(obj2 == internalObj); // Ensure it always use the same object instance
+ Test.AssertEquals(obj2.NativeConstructionCount, 1); // And that constructors are not called again
+
+ obj.Dispose();
+ obj2.Dispose();
+ }
+}
+
+}
diff --git a/src/tests/efl_mono/dummy_constructible_object.c b/src/tests/efl_mono/dummy_constructible_object.c
new file mode 100644
index 0000000000..96842709ba
--- /dev/null
+++ b/src/tests/efl_mono/dummy_constructible_object.c
@@ -0,0 +1,70 @@
+#include "libefl_mono_native_test.h"
+
+typedef struct _Dummy_Constructible_Object_Data
+{
+ Eo *internal_obj;
+ int native_construction_count;
+ int default_construction_count;
+ int special_construction_count;
+} Dummy_Constructible_Object_Data;
+
+
+EOLIAN static Eo *
+_dummy_constructible_object_efl_object_constructor(Eo *obj, Dummy_Constructible_Object_Data *pd)
+{
+ ++(pd->native_construction_count);
+ return efl_constructor(efl_super(obj, DUMMY_CONSTRUCTIBLE_OBJECT_CLASS));
+}
+
+EOLIAN static void
+_dummy_constructible_object_efl_object_destructor(Eo *obj, Dummy_Constructible_Object_Data *pd)
+{
+ if (pd->internal_obj)
+ efl_unref(pd->internal_obj);
+ efl_destructor(efl_super(obj, DUMMY_CONSTRUCTIBLE_OBJECT_CLASS));
+}
+
+EOLIAN static Efl_Object *
+_dummy_constructible_object_construct_type_and_store(Eo *obj EINA_UNUSED, Dummy_Constructible_Object_Data *pd, const Efl_Class *klass)
+{
+ pd->internal_obj = efl_add_ref(klass, NULL);
+ return pd->internal_obj;
+}
+
+EOLIAN static void
+_dummy_constructible_object_increment_default_construction_count(Eo *obj EINA_UNUSED, Dummy_Constructible_Object_Data *pd)
+{
+ ++(pd->default_construction_count);
+}
+
+EOLIAN static void
+_dummy_constructible_object_increment_special_construction_count(Eo *obj EINA_UNUSED, Dummy_Constructible_Object_Data *pd)
+{
+ ++(pd->special_construction_count);
+}
+
+EOLIAN static int
+_dummy_constructible_object_native_construction_count_get(const Eo *obj EINA_UNUSED, Dummy_Constructible_Object_Data *pd)
+{
+ return pd->native_construction_count;
+}
+
+EOLIAN static int
+_dummy_constructible_object_default_construction_count_get(const Eo *obj EINA_UNUSED, Dummy_Constructible_Object_Data *pd)
+{
+ return pd->default_construction_count;
+}
+
+EOLIAN static int
+_dummy_constructible_object_special_construction_count_get(const Eo *obj EINA_UNUSED, Dummy_Constructible_Object_Data *pd)
+{
+ return pd->special_construction_count;
+}
+
+EOLIAN static Efl_Object *
+_dummy_constructible_object_internal_object_get(const Eo *obj EINA_UNUSED, Dummy_Constructible_Object_Data *pd)
+{
+ return pd->internal_obj;
+}
+
+#include "dummy_constructible_object.eo.c"
diff --git a/src/tests/efl_mono/dummy_constructible_object.eo b/src/tests/efl_mono/dummy_constructible_object.eo
new file mode 100644
index 0000000000..f8ae944e6c
--- /dev/null
+++ b/src/tests/efl_mono/dummy_constructible_object.eo
@@ -0,0 +1,47 @@
+class Dummy.Constructible_Object extends Efl.Object {
+ methods {
+ construct_type_and_store {
+ params {
+ @in type: const(Efl.Class);
+ }
+ return: Efl.Object;
+ }
+ increment_default_construction_count {
+ }
+ increment_special_construction_count {
+ }
+ @property native_construction_count {
+ get {
+ }
+ values {
+ value: int;
+ }
+ }
+ @property default_construction_count {
+ get {
+ }
+ values {
+ value: int;
+ }
+ }
+ @property special_construction_count {
+ get {
+ }
+ values {
+ value: int;
+ }
+ }
+ @property internal_object {
+ get {
+ }
+ values {
+ value: Efl.Object;
+ }
+ }
+ }
+ implements {
+ Efl.Object.constructor;
+ Efl.Object.destructor;
+ }
+}
+
diff --git a/src/tests/efl_mono/dummy_test_object.c b/src/tests/efl_mono/dummy_test_object.c
index fa5d01888a..f9b276c085 100644
--- a/src/tests/efl_mono/dummy_test_object.c
+++ b/src/tests/efl_mono/dummy_test_object.c
@@ -56,9 +56,9 @@ Dummy_Numberwrapper **_new_obj_ref(int n)
return &r;
}
-// ############ //
-// Test.Testing //
-// ############ //
+// ################# //
+// Dummy.Test_Object //
+// ################# //
static Efl_Object*
_dummy_test_object_efl_object_constructor(Eo *obj, Dummy_Test_Object_Data *pd)
diff --git a/src/tests/efl_mono/libefl_mono_native_test.h b/src/tests/efl_mono/libefl_mono_native_test.h
index 9251118fc6..b726bd05c1 100644
--- a/src/tests/efl_mono/libefl_mono_native_test.h
+++ b/src/tests/efl_mono/libefl_mono_native_test.h
@@ -55,6 +55,7 @@
#include "dummy_inherit_helper.eo.h"
#include "dummy_part_holder.eo.h"
#include "dummy_event_manager.eo.h"
+#include "dummy_constructible_object.eo.h"
#include <interfaces/efl_part.eo.h>
diff --git a/src/tests/efl_mono/meson.build b/src/tests/efl_mono/meson.build
index f75a5b8bb9..e464cdd2a8 100644
--- a/src/tests/efl_mono/meson.build
+++ b/src/tests/efl_mono/meson.build
@@ -7,6 +7,7 @@ eo_files = [
'dummy_inherit_iface.eo',
'dummy_part_holder.eo',
'dummy_event_manager.eo',
+ 'dummy_constructible_object.eo',
]
eo_file_targets = []
@@ -33,6 +34,7 @@ efl_mono_native_test = library('efl_mono_native_test',
'dummy_part_holder.c',
'dummy_test_object.c',
'dummy_event_manager.c',
+ 'dummy_constructible_object.c',
],
dependencies : [ecore, eo, efl],
)
@@ -65,6 +67,7 @@ efl_mono_src = [
'Eldbus.cs',
'Eo.cs',
'EoPromises.cs',
+ 'EoConstruction.cs',
'Errors.cs',
'Events.cs',
'FunctionPointers.cs',